Analyze a suspicious PowerShell script from a Windows host (CyberChef suggested for decoding).
A suspicious PowerShell script wrapped its real logic in a base64 blob passed to powershell as an encoded command. The launcher arguments hid the window and ran it non-interactively, so a user would never see or interrupt it. The decoded script built a .NET web client, set a spoofed browser user agent so its traffic blended in with normal browsing, and reused the logged-in user’s default credentials to get through an authenticating proxy. It then contacted a hardcoded HTTP address on a non-standard port to fetch the payload. Everything was recovered statically by decoding the blob; nothing was executed.
script.ps1 → read as text. A PowerShell launcher line with an -Enc argument holding the payloadEncoding note: PowerShell’s
-EncodedCommandis base64 over UTF-16LE text, so a plain base64 decode shows null-byte-spaced garbage. Convert from UTF-16LE after decoding. CyberChef does the same with From Base64 then Decode text (UTF-16LE).
The launcher line in script.ps1 passes the payload through -Enc, the short form of -EncodedCommand. That switch takes base64 of UTF-16LE text, which is why the blob decodes cleanly only once the UTF-16LE step is added.
base64 -d script.ps1 | iconv -f UTF-16LE -t UTF-8
The answer is in the launcher arguments, not in the decoded body. Read the switches in front of -Enc: the window-style switch is written in its short form with the value Hidden, so no console window appears when the script runs.
cat script.ps1
Same launcher line. -NonI is the short form of -NonInteractive, which runs PowerShell without an interactive prompt, so there is nothing for the user to interact with or dismiss. Together with the hidden window it keeps the process out of sight.
cat script.ps1
Gotcha: The question wording suggests a “prevent close” switch, but the parameter that matches the four-character format hint is the non-interactive one.
Decode the blob and look for the object that does the networking. The script instantiates a .NET System.Net.WebClient. The casing is deliberately mixed (New-ObjEcT, SySTeM.NET.WebCliENt), a cheap signature-evasion trick, so copy the line exactly as it appears.
base64 -d script.ps1 | iconv -f UTF-16LE -t UTF-8
The next lines of the decoded script set the web client’s user agent. It claims to be Internet Explorer 11 on Windows 7 (Trident/7.0; rv:11.0), which makes the request look like ordinary browser traffic in proxy logs.
base64 -d script.ps1 | iconv -f UTF-16LE -t UTF-8
The script assigns the client’s proxy credentials from the system credential cache, so it authenticates to a corporate proxy as whoever is logged in without needing a stored password. Again the casing is scrambled, and the answer must match it character for character.
base64 -d script.ps1 | iconv -f UTF-16LE -t UTF-8
The payload address is hardcoded in the decoded script: a plain HTTP URL to a bare IP on port 7443, ending in an .asp page. The IP and non-standard port make it a good block-list and proxy-log pivot.
base64 -d script.ps1 | iconv -f UTF-16LE -t UTF-8
| Phase | Action |
|---|---|
| Execution | PowerShell launched with an encoded command (-Enc) carrying a base64 UTF-16LE payload |
| Defense Evasion | Hidden window and non-interactive mode keep the process invisible to the user |
| Defense Evasion | Mixed-case cmdlet and type names dodge simple string signatures |
| Command and Control | WebClient created with a spoofed IE11 user agent |
| Command and Control | Default network credentials set as proxy credentials to pass an authenticating proxy |
| Command and Control | Payload requested from a hardcoded HTTP URL on port 7443 |
| Type | Value |
|---|---|
| URL | hxxp[://]98[.]103[.]103[.]170[:]7443/index[.]asp |
| IP | 98[.]103[.]103[.]170 |
| User agent | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko |
| Launcher switches | -W Hidden, -NonI, -Enc |
| Technique | ID | Description |
|---|---|---|
| Command and Scripting Interpreter: PowerShell | T1059.001 | Encoded PowerShell launcher |
| Obfuscated Files or Information: Command Obfuscation | T1027.010 | Base64 payload and mixed-case names |
| Hide Artifacts: Hidden Window | T1564.003 | -W Hidden |
| Application Layer Protocol: Web Protocols | T1071.001 | HTTP request with a spoofed browser user agent |
| Ingress Tool Transfer | T1105 | Script contacts a hardcoded URL for the payload |
Encoded PowerShell with hidden-window switches is a detection primitive on its own. A command line combining -Enc, -W Hidden and -NonI is rarely legitimate. Alert on that combination in process-creation logs (Sysmon 1 or 4688 with command-line auditing) and in PowerShell Script Block Logging, which records the decoded script.
Case-mangled cmdlets defeat case-sensitive matching. New-ObjEcT and SySTeM.NET.WebCliENt slip past naive string rules. Normalise case before matching, or key on behaviour such as Net.WebClient use from a hidden PowerShell process.
A spoofed user agent is only convincing until it is compared with the process. An IE11 user agent from powershell.exe is a mismatch worth hunting in proxy logs. Pair user-agent analytics with the originating process.
Default proxy credentials mean the proxy cannot save you from an authenticated user. Because the script borrows the logged-in identity, proxy authentication gives no protection. Restrict egress to known destinations and block direct-to-IP HTTP on odd ports like 7443.
The whole payload chain was recoverable with one decode: a hidden, non-interactive PowerShell launcher that borrowed the user’s proxy identity and pulled a payload from a bare IP. Base64 added no real protection, so logging decoded script content is what turns this from invisible into trivial to catch.