Skip to content

francose/windows_malware

Repository files navigation

windows_malware — Educational Reverse-Shell Lab

A small, localhost-only lab that walks through a complete Windows initial-access chain end-to-end:

malware.bat / payload.bat        (obfuscated dropper, runs on "victim")
        │
        └──>  mshta + VBScript   (T1218.005)
                  │
                  └──>  powershell -EncodedCommand   (T1059.001 + T1027)
                            │
                            └──>  IEX(DownloadString(...))   (T1105)
                                      │
                                      └──>  reverse.ps1   (T1059.001)
                                                │
                                                └──>  TCP 127.0.0.1:9001  -->  nc -lvnp 9001

Everything runs against 127.0.0.1. There is no real target. This is a teaching artifact for OSCP / red-team / detection-engineering students who want to read and run each stage without setting up a multi-VM lab.

⚠️ Lab use only. Run this against systems you own. See LICENSE.


What's in the box

Lab chain

File Role What to read it for
server.py Minimal HTTP "C2" stand-in (8080). Serves payload.bat and reverse.ps1. LOLBin delivery; hosting + logging
payload.bat Plain mshta + VBScript dropper. Smallest readable form of the chain. How the encoded-PowerShell handoff actually looks
malware.bat Same payload, wrapped in batch-level obfuscation (8-part assembly, decoys, time-branching). What batch obfuscation looks like — and what it does NOT defeat
reverse.ps1 TCP reverse shell with reconnect + UTF-8 streaming + ScriptBlock-isolated iex. Reverse-shell ergonomics; AMSI-visible PowerShell
obfuscation-techniques.md Walks each obfuscation technique in malware.bat. Read with detection-and-defense.md open. What each layer is and isn't doing
detection-and-defense.md Honest companion: AMSI, ScriptBlock Logging (4104), ETW, Sysmon. What catches each layer in 2026. The reality check

Operator tools (tools/)

Tool Output
tools/encode_ps.py Encode/decode PowerShell -EncodedCommand (base64 + UTF-16LE). Dual-use — IR uses this on captured payloads.
tools/build_chain.py Reconfigure the lab for a fresh LHOST/LPORT/HTTP host. Regenerates the base64 in payload.bat, server.py, and reverse.ps1 in one shot. Prints a runbook.
tools/lolbin_droppers.py Same payload URL → 13 LOLBin dropper one-liners (mshta, regsvr32, rundll32, wmic, certutil, bitsadmin, msiexec, cscript, msbuild, curl, three PowerShell flavors), each tagged with its MITRE ID and parent-child chain. Useful for studying the catalog and writing detections for it.
tools/listener.py Stdlib TCP listener with timestamps + per-session log files + post-drop wait. Replaces nc -lvnp when you want logs.
tools/obfuscate_ps.py 8 command-line obfuscation transforms (backtick, concat, format, variable, reverse, case, env-binary, split-flags). Defeats string-match rules, not AMSI — see detection-and-defense.md.

All tools are stdlib-only, single-file, CLI-first. Same MIT / lab-use terms.


Setup

Requires Python 3.8+, nc (netcat) or ncat, and a Windows host or VM with PowerShell 5+.

The server and listener can run on WSL, Kali, or any Linux box, and the dropper runs on the same machine (or a separate Windows host on the same network if you set LISTENER_HOST accordingly). All defaults assume everything on one box.

1. Start the listener (terminal 1)

nc -lvnp 9001

2. Start the HTTP C2 (terminal 2)

python server.py

You'll see endpoint registrations and a hint about the listener.

3. Trigger the dropper (terminal 3 — Windows / cmd.exe)

Run one of:

payload.bat

or — to exercise the obfuscation chain:

malware.bat

A PS C:\...> prompt should appear in the netcat terminal. Type whoami, Get-Process | select -First 5, etc.

Optional — remote target

Use tools/build_chain.py to regenerate every file with new addresses in one shot:

python tools/build_chain.py \
    --lhost 10.10.14.5  --lport 4444 \
    --http-host 10.10.14.5 --http-port 8000 \
    --write

That rewrites payload.bat, reverse.ps1, and server.py with the new base64 and prints the runbook (listener command, target one-liner, etc.).


What the obfuscation actually buys you

Almost nothing against modern defenders. The PowerShell stage is plaintext to AMSI the instant -EncodedCommand is decoded — the batch wrapper's 8-part assembly, XOR decoys, and time-branched control flow never reach the AV's view of the payload. See detection-and-defense.md for the full breakdown of which layers help, which are theatre, and what kills each one.

This is intentional. The repo's job is to make those failure modes legible by showing you a complete chain and then telling you exactly where it falls apart.


Learning objectives

After reading and running this, you should be able to:

  • Explain the LOLBin delivery chain: cmd → mshta → wscript → powershell and why each step exists.
  • Read PowerShell -EncodedCommand payloads by base64-decoding from UTF-16LE.
  • Identify which obfuscation layers an analyst will see in static review vs. dynamic.
  • Point to the specific Windows logging primitives that defeat each layer (AMSI, EID 4104, Sysmon EID 1, ETW PowerShell provider).
  • Articulate why mshta + VBScript is end-of-life on Windows 11 23H2+.

What's deliberately not here

  • AMSI bypass code. Public bypasses are detected and rotate quickly; this lab is about understanding the surface, not chasing a bypass treadmill.
  • Persistence. Out of scope.
  • Privilege escalation. Out of scope.
  • Real C2 framework integration. If you want this against Sliver / Mythic / Havoc, swap server.py for the framework's stager.

Suggested exercises

  1. Run malware.bat with Defender enabled. Note the alert path (file, then payload, then network).
  2. Enable PowerShell ScriptBlock Logging (HKLM\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging\EnableScriptBlockLogging = 1) and observe Event ID 4104 in Microsoft-Windows-PowerShell/Operational — the decoded script appears in full.
  3. Watch Sysmon Event ID 1 for the parent chain cmd.exe → mshta.exe → powershell.exe. That single transition is a high-fidelity rule on its own.
  4. Modify reverse.ps1 to remove the iex-equivalent ([ScriptBlock]::Create) and see whether AMSI still flags it.

License

MIT. Educational use only.

About

A Python HTTP server hosts a PowerShell reverse shell script. PowerShell downloads and executes it, connecting back to a Netcat listener. This exploits trusted system utilities for stealthy remote access.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors