<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://www.joshuaberkoh.engineer/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.joshuaberkoh.engineer/" rel="alternate" type="text/html" /><updated>2026-08-15T06:29:14+00:00</updated><id>https://www.joshuaberkoh.engineer/feed.xml</id><title type="html">Joshua Berkoh</title><subtitle>Cyber Threat Intelligence Lab — threat investigations, intelligence analysis, threat hunting, and dark-web research by Joshua Berkoh.</subtitle><author><name>Joshua Offe Berkoh</name></author><entry><title type="html">Building a Malware Reversing Lab on Proxmox</title><link href="https://www.joshuaberkoh.engineer/research/malware-reversing-lab/" rel="alternate" type="text/html" title="Building a Malware Reversing Lab on Proxmox" /><published>2026-03-26T00:00:00+00:00</published><updated>2026-03-26T00:00:00+00:00</updated><id>https://www.joshuaberkoh.engineer/research/building-a-malware-reversing-lab-on-proxmox</id><content type="html" xml:base="https://www.joshuaberkoh.engineer/research/malware-reversing-lab/"><![CDATA[<div class="lab-post">
  <div class="lab-post-tags">
    <span class="tag tag-red">Malware Analysis</span>
    <span class="tag tag-green">Detection Engineering</span>
    <span class="tag tag-blue">Proxmox</span>
    <span class="tag tag-amber">Lab Build</span>
  </div>

  <p class="lab-post-lead">
    This lab is built around a simple goal: move from malware behavior to validated defensive logic.
    It combines a controlled reverse engineering environment with a detection engineering workflow so
    that every detonation can produce telemetry, hypotheses, and immediately testable detections.
  </p>

  <div class="insight-grid">
    <div class="insight-card">
      <p class="insight-label">Why this matters</p>
      <p>Reverse engineering is more valuable when it improves coverage, tuning, and confidence in real detection logic.</p>
    </div>
    <div class="insight-card">
      <p class="insight-label">Research fit</p>
      <p>This mirrors how I approach security work: rigorous technical analysis tied directly to practical operational outcomes.</p>
    </div>
    <div class="insight-card">
      <p class="insight-label">Core loop</p>
      <p>Detonate, observe, collect telemetry, validate detections, revert, and repeat from a known baseline.</p>
    </div>
  </div>

  <div class="callout callout-info">
    <div class="callout-title">Key outcomes</div>
    <ul class="callout-list">
      <li>Isolated malware execution with a constrained blast radius.</li>
      <li>One-way telemetry into Elastic for live rule validation.</li>
      <li>Repeatable snapshot-based analysis sessions.</li>
      <li>A workflow that aligns malware reverse engineering with threat detection engineering.</li>
    </ul>
  </div>

  <div class="toc-inline">
    <p>Contents</p>
    <ol>
      <li><a href="#design-principles">Design principles</a></li>
      <li><a href="#network">Network architecture</a></li>
      <li><a href="#reversing-vms">The reversing VMs</a></li>
      <li><a href="#tooling">Tooling breakdown</a></li>
      <li><a href="#de-lab">Detection engineering lab</a></li>
      <li><a href="#telemetry">Telemetry bridge</a></li>
      <li><a href="#snapshot">Snapshot workflow</a></li>
      <li><a href="#closing">Closing thoughts</a></li>
    </ol>
  </div>

  <h2 id="design-principles" class="anchor">1. Design Principles</h2>

  <p>
    Before allocating a single VM, it helps to define what the lab is actually trying to accomplish,
    because that shapes every architectural decision that follows.
  </p>
  <p>
    The core goal here is a <em>closed-loop pipeline</em>: analyze a malware sample, observe its
    behavior, and immediately validate whether your detection rules in Elastic would have caught it.
    This requires two capabilities to coexist on the same infrastructure, a reversing environment
    and a detection engineering stack, while remaining strictly isolated at the network layer.
  </p>

  <p>Three principles govern the architecture:</p>
  <ul>
    <li><strong>Hard network isolation.</strong> Malware executes in a segment with no direct path to the public internet or the rest of the lab.</li>
    <li><strong>One-way telemetry.</strong> Logs flow out of the reversing environment into the SIEM. Nothing flows back in.</li>
    <li><strong>Snapshot-driven analysis.</strong> Every detonation begins from a known-clean baseline and ends with a revert.</li>
  </ul>

  <div class="callout callout-tip">
    <div class="callout-title">Framing</div>
    <p>This lab is intentionally described in terms of workflow and security boundaries rather than hardware inventory. The value is in the method, not the exposed infrastructure details.</p>
  </div>

  <h2 id="network" class="anchor">2. Network Architecture</h2>

  <p>
    Proxmox manages isolation through Linux bridges. The setup uses one management network for the
    detection stack and one internal-only network for controlled malware execution.
  </p>
  <ul>
    <li><code>vmbr1</code> acts as the management bridge for the detection lab and supporting services.</li>
    <li><code>vmbr2</code> is an internal-only bridge with no physical uplink. Malware executes here.</li>
  </ul>

  <p>
    Creating the isolated bridge in Proxmox requires adding a bridge without a port assignment
    in <code>/etc/network/interfaces</code>:
  </p>

  <pre data-lang="shell"><code><span class="cm"># Add below existing vmbr1 config in /etc/network/interfaces</span>
<span class="kw">auto</span> vmbr2
<span class="kw">iface</span> vmbr2 inet static
    address  10.10.20.1/24
    bridge-ports none
    bridge-stp   off
    bridge-fd    0</code></pre>

  <p>
    The absence of <code>bridge-ports</code> is what makes it internal-only. Traffic can flow between
    VMs on <code>vmbr2</code>, but it never touches a physical NIC.
  </p>
  <p>
    The Windows Dynamic VM gets <em>two</em> NICs: one on <code>vmbr2</code> for execution and one on
    <code>vmbr1</code> for outbound telemetry. The management-facing NIC has no default gateway and
    exists purely to move logs into Elastic.
  </p>

  <div class="arch-diagram">
    <div class="arch-host">
      <div class="arch-host-label">Virtualization host</div>
      <div class="arch-row">
        <div class="arch-zone arch-zone-red">
          <div class="arch-zone-label">Reversing lab - vmbr2 (no uplink)</div>
          <div class="arch-vm"><span class="arch-vm-name">Windows-Static</span><span class="arch-vm-desc">static analysis only</span></div>
          <div class="arch-vm"><span class="arch-vm-name">Windows-Dynamic</span><span class="arch-vm-desc">detonation + outbound telemetry</span></div>
        </div>
        <div class="arch-zone arch-zone-teal">
          <div class="arch-zone-label">Detection lab - vmbr1 (management)</div>
          <div class="arch-vm"><span class="arch-vm-name">elastic-stack</span><span class="arch-vm-desc">ELK · Fleet · SIEM</span></div>
          <div class="arch-vm"><span class="arch-vm-name">supporting endpoints</span><span class="arch-vm-desc">victim and validation systems</span></div>
        </div>
      </div>
      <div class="arch-zone arch-zone-purple arch-zone-spaced">
        <div class="arch-zone-label">Telemetry path - one-way</div>
        <div class="arch-arrow">Windows-Dynamic (Elastic Agent) -&gt; vmbr1 -&gt; elastic-stack (Fleet Server) -&gt; SIEM · KQL rules</div>
      </div>
    </div>
  </div>

  <h2 id="reversing-vms" class="anchor">3. The Reversing VMs</h2>

  <p>
    The reversing environment follows a two-VM model: a <strong>Static VM</strong> and a
    <strong>Dynamic VM</strong> that are full clones of each other, differentiated by which additional
    tools are installed and by desktop color, black for Static and green for Dynamic. The visual split
    sounds minor, but it reduces operator error during an active session.
  </p>

  <h3>Why two VMs instead of one?</h3>

  <p>
    Static analysis, examining PE headers, strings, imports, and disassembly, should never happen
    in the same environment where samples execute. Once a Dynamic VM has run malware, its registry,
    filesystem, and network state are potentially dirty. A Static VM that never executes anything
    preserves a clean context for analysis.
  </p>

  <h3>Base VM configuration</h3>

  <p>Both VMs run Windows 11 Pro with the following hardening applied before cloning:</p>
  <ul>
    <li>UAC disabled via the settings slider (set to <em>Never notify</em>).</li>
    <li>Windows Defender disabled through Group Policy, registry edits, and scheduled task cleanup.</li>
    <li>Windows Update constrained by marking the interface as metered.</li>
    <li>File extensions shown in Explorer.</li>
    <li>OneDrive and telemetry-heavy inbox applications removed.</li>
    <li>Local account only, with no Microsoft account association.</li>
  </ul>

  <div class="callout callout-danger">
    <div class="callout-title">Defender persistence</div>
    <p>Disabling Defender requires policy-level persistence, not just the Settings UI toggle. If the protection stack comes back after reboot, the baseline is no longer trustworthy.</p>
  </div>

  <p>
    The Dynamic VM is provisioned more generously because it carries a heavier concurrent workload:
    debugger activity, file and registry monitoring, packet capture, protocol interception, and
    Elastic telemetry forwarding at the same time.
  </p>

  <h2 id="tooling" class="anchor">4. Tooling Breakdown</h2>

  <p>
    All tools live under <code>C:\Tools\</code>, with <code>C:\Tools\bin\</code> on the system
    PATH for CLI tooling. That keeps the environment predictable and removes friction during active analysis.
  </p>

  <h3>Static analysis tools (both VMs)</h3>

  <div class="tool-grid">
    <div class="tool-item"><div class="tool-dot dot-gray"></div><div><div class="tool-name">PEStudio v9.58</div><div class="tool-desc">PE file analysis; imports, sections, red flags without execution</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-gray"></div><div><div class="tool-name">PE-bear</div><div class="tool-desc">Lightweight; handles malformed PE headers well</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-gray"></div><div><div class="tool-name">CFF Explorer</div><div class="tool-desc">Accurate PE header field names per spec; supports direct editing</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-gray"></div><div><div class="tool-name">DIE + Exeinfo</div><div class="tool-desc">Packer and file-type identification; dual signature databases</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-gray"></div><div><div class="tool-name">FLOSS</div><div class="tool-desc">Extracts encoded and obfuscated strings from executables</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-gray"></div><div><div class="tool-name">QuantumStrand</div><div class="tool-desc">Adds context to extracted strings; accelerates hypothesis formation</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-gray"></div><div><div class="tool-name">YARA + YARA Forge</div><div class="tool-desc">Pattern matching against the full community-maintained ruleset</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-gray"></div><div><div class="tool-name">capa</div><div class="tool-desc">Capability identification mapped to MITRE ATT&amp;CK techniques</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-gray"></div><div><div class="tool-name">Binary Ninja Free</div><div class="tool-desc">Disassembler and decompiler; sufficient for course-level analysis</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-gray"></div><div><div class="tool-name">CyberChef (local)</div><div class="tool-desc">Decoding, encoding, and transformation; runs fully offline</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-gray"></div><div><div class="tool-name">HxD</div><div class="tool-desc">Hex editor; raw byte inspection and editing</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-gray"></div><div><div class="tool-name">UPX</div><div class="tool-desc">Common packer; useful for understanding packed binary characteristics</div></div></div>
  </div>

  <h3>Dynamic analysis tools (Dynamic VM only)</h3>

  <div class="tool-grid">
    <div class="tool-item"><div class="tool-dot dot-red"></div><div><div class="tool-name">x64dbg + x32dbg</div><div class="tool-desc">Primary debugger; plugins: OllyDumpEx, ScyllaHide, xAnalyzer</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-red"></div><div><div class="tool-name">Process Monitor</div><div class="tool-desc">Real-time file system, registry, and process event capture</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-red"></div><div><div class="tool-name">System Informer</div><div class="tool-desc">Process inspection; modules, memory regions, network activity</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-red"></div><div><div class="tool-name">FakeNet-NG</div><div class="tool-desc">Intercepts and simulates DNS, HTTP, and other protocols locally</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-red"></div><div><div class="tool-name">Regshot</div><div class="tool-desc">Registry + filesystem diff before and after execution</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-red"></div><div><div class="tool-name">Wireshark</div><div class="tool-desc">PCAP capture of FakeNet-NG traffic; C2 communication analysis</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-red"></div><div><div class="tool-name">API Monitor x86 + x64</div><div class="tool-desc">Hooks and records Windows API calls without stepping a debugger</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-red"></div><div><div class="tool-name">Speakeasy</div><div class="tool-desc">User-mode Windows emulation; analyze without full OS execution</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-red"></div><div><div class="tool-name">Scylla x86 + x64</div><div class="tool-desc">IAT reconstruction post-unpack; recover usable dumped executables</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-red"></div><div><div class="tool-name">mal_unpack</div><div class="tool-desc">Executes obfuscated malware and identifies injected or unpacked code</div></div></div>
    <div class="tool-item"><div class="tool-dot dot-green"></div><div><div class="tool-name">Elastic Agent</div><div class="tool-desc">Ships process, network, file, and registry events to Fleet over vmbr1</div></div></div>
  </div>

  <div class="callout callout-tip">
    <div class="callout-title">Integration note</div>
    <p>Elastic Agent is the one addition beyond the standard malware analysis toolchain. It captures process, network, file, and registry activity and forwards it into Fleet in near real time as a sample executes.</p>
  </div>

  <h2 id="de-lab" class="anchor">5. The Detection Engineering Lab</h2>

  <p>
    The detection engineering side of the lab predates the reversing environment and runs alongside it
    on the management network.
  </p>
  <ul>
    <li><strong>elastic-stack</strong> receives telemetry, hosts Fleet, and serves as the detection engineering workspace.</li>
    <li><strong>supporting Windows systems</strong> provide victim and validation endpoints for controlled testing.</li>
    <li><strong>supporting Linux systems</strong> provide operator and infrastructure support for the wider lab.</li>
  </ul>
  <p>
    This side of the environment follows the same philosophy as my broader work: use disciplined,
    observable systems to produce useful defensive outcomes rather than isolated technical artifacts.
  </p>

  <h2 id="telemetry" class="anchor">6. The Telemetry Bridge</h2>

  <p>
    This is the part of the design that makes the lab more than two parallel environments.
  </p>
  <p>
    When malware executes on the Dynamic VM, Elastic Agent captures events in near real time. Within
    seconds of a sample spawning a child process, writing persistence keys, or attempting a network
    connection, those events are queryable in Kibana. You can run KQL detections against the live
    stream and see immediately whether the logic fires, misses, or over-alerts.
  </p>
  <p>
    That feedback loop is difficult to reproduce with synthetic datasets. Real malware produces real
    telemetry, along with the timing artifacts and edge cases that simulations often smooth over.
    Repeatedly testing against that reality builds stronger, more durable detection logic.
  </p>

  <div class="callout callout-info">
    <div class="callout-title">Operational value</div>
    <p>This is the strongest alignment point with my own background: not just understanding behavior, but converting that understanding into measurable defensive improvement.</p>
  </div>

  <p>A few implementation details worth noting:</p>
  <ul>
    <li>The management-facing NIC on the Dynamic VM has no default gateway; it exists purely for telemetry transport.</li>
    <li>Fleet enrollment uses a policy centered on Windows telemetry collection and detection validation.</li>
    <li>The Static VM intentionally has no Elastic Agent because it should never produce execution telemetry.</li>
  </ul>

  <h2 id="snapshot" class="anchor">7. Snapshot Workflow</h2>

  <p>
    The snapshot discipline is what keeps the reversing environment trustworthy over time. The
    workflow must be followed without exception:
  </p>
  <ol>
    <li>Revert the Dynamic VM to the <strong>Dynamic Baseline</strong> snapshot before every session.</li>
    <li>Take a Regshot first snapshot before executing anything.</li>
    <li>Start Process Monitor and Wireshark captures.</li>
    <li>Launch FakeNet-NG with administrator privileges.</li>
    <li>Execute the sample.</li>
    <li>Observe behavior and allow Elastic Agent time to forward events to the SIEM.</li>
    <li>Take a Regshot second snapshot and compare the diff.</li>
    <li>Save the PCAP, ProcMon log, and any memory dumps.</li>
    <li>Review which KQL detection rules fired in Kibana.</li>
    <li>Revert to <strong>Dynamic Baseline</strong>.</li>
  </ol>

  <p>In Proxmox, snapshot creation and revert are both straightforward from the CLI:</p>

  <pre data-lang="shell"><code><span class="cm"># Create the named baseline snapshot</span>
<span class="fn">qm</span> snapshot &lt;vmid&gt; <span class="st">"Dynamic Baseline"</span> \
  --description <span class="st">"Clean state, all tools installed, Defender off, Agent enrolled"</span>

<span class="cm"># Revert before every analysis session</span>
<span class="fn">qm</span> rollback &lt;vmid&gt; <span class="st">"Dynamic Baseline"</span></code></pre>

  <div class="callout callout-info">
    <div class="callout-title">Elastic Agent and snapshot revert</div>
    <p>Rolling back a snapshot resets the VM state, including the local event buffer. That is expected. The useful telemetry has already been forwarded, and the baseline restores the environment to a trustworthy starting point.</p>
  </div>

  <h2 id="closing" class="anchor">8. Closing Thoughts</h2>

  <p>
    The most valuable part of this architecture is the feedback loop between the reversing environment
    and the detection stack. Reverse engineering in isolation explains what a sample does. Watching
    your SIEM respond in real time shows whether your detections would actually catch it in practice.
  </p>

  <p>A few things worth improving next:</p>
  <ul>
    <li>Add faster storage for analysis-heavy workloads.</li>
    <li>Extend the fake network layer for more complex protocol emulation.</li>
    <li>Archive PCAPs and artifacts in a way that supports cross-sample correlation over time.</li>
  </ul>

  <p>
    Follow-up posts will cover network segmentation in more detail, writing Elastic detections from
    malware telemetry, and extending the lab for evasion analysis. If you run a similar setup or want
    to compare approaches, feel free to reach out.
  </p>

  <div class="callout callout-tip">
    <div class="callout-title">Research note</div>
    <p>This environment supports the kind of work I want to keep doing: reverse engineering, telemetry-driven validation, and secure systems thinking that can hold up under real operational constraints.</p>
  </div>

  <div class="next-steps">
    <p class="insight-label">Next in this series</p>
    <ul>
      <li>Detailed Proxmox network segmentation for malware labs.</li>
      <li>Writing Elastic detections from real malware telemetry.</li>
      <li>Extending the lab for evasion testing and longitudinal sample analysis.</li>
    </ul>
  </div>

  <hr class="divider" />
  <div class="lab-post-tags">
    <span class="tag tag-red">Malware Analysis</span>
    <span class="tag tag-green">Detection Engineering</span>
    <span class="tag tag-blue">Proxmox</span>
    <span class="tag tag-amber">Lab Build</span>
    <span class="tag tag-purple">Elastic SIEM</span>
  </div>
</div>]]></content><author><name>Joshua Berkoh</name></author><category term="threat-detection" /><category term="Malware Analysis" /><category term="Proxmox" /><category term="Elastic SIEM" /><summary type="html"><![CDATA[A walkthrough of the full architecture for a dual-purpose home lab: a Windows-based reversing environment for static and dynamic malware analysis, running alongside a detection engineering stack on the same bare-metal server and feeding telemetry into Elastic SIEM.]]></summary></entry></feed>