IT Administrators and Security Specialists often run into a suspicious looking PowerShell command; sometimes they succeed in decoding them but often, they are reliant on researchers. This blog should serve as a guidance to identify the purpose of suspicious entries found in:

  • Scheduled Tasks
  • RUN Keys in the Registry
  • Static PowerShell Scripts
  • Proxy Logs if a Web Server is exploited for a Remote Code Execution

powershell.exe -EncodedCommand JABzAHIAdgBzAHkAcw..

Here’s an Autoruns export from a server which was exhibiting repeated Sophos HIPS detection at regular intervals. Upon checking the logs carefully, you can easily spot a bunch services with random characters as Service Name. This attribute of a Windows Service stands out which is of immediate interest!


There’s no reason for a service like this to be present on a Windows Server. As expected, an administrator is unwary of anything like this which confirms our suspicion of it being malicious in nature.

This tactic is called Living-Off-The-Land a.k.a LOLBins i.e. perform malicious activities without dropping any binary/executable/malware on the disk. Why? You know the answer – to avoid tripping any alarms because historically, static [file] based detection is how AVs have evolved. AVs cannot completely move away from this technique however we do keep adding more layers to protect and prevent end-user machines.

At this point you would need means to decode the long string of characters to find out the malware’s endgame. The extraaaaa looooong string of characters is what we call a Base64 Encoded Data.

“Base64 encoding schemes are commonly used to represent binary data in ASCII text. Any binary data is represented in text using only 64 characters from Ascii set. Base64 encoding is a process of converting binary data to an ASCII string format by converting that binary data into a 6-bit character representation. The Base64 method of encoding is used when binary data, such as images or video or malicious scripts/programs, is transmitted over systems that are designed to transmit data in a plain-text (ASCII) format.”

Here’s a quick Cheat Sheet of Base64 Encoding I’ve put together –

Base64 Code





Variable Declaration (UTF-16)



MZ Header



PowerShell Invoke Expression



PowerShell Invoke Expression (UTF-16)



PowerShell Invoke string (UTF-16) e.g. Invoke-MimiKatz



Often used by Emotet [Malicious Document pulling down Emotet binary) (UTF-16)



PowerShell Invoke Expression



PowerShell Invoke Expression (UTF-16)



Variable Declaration



Variable Declaration (UTF-16)



gzip magic bytes (0x1f8b)

The string  JABz[..truncated..]IAagBwA= cin its most basic form is an onion. It has several layers to cleverly hide what it’s supposed to do in order to evade detection. But unlike an onion, it only has 3 Layers before we get to our Golden Egg. Let’s take a walk through each layer.

Layer 1 – Episode 1

This string can be decoded into a human readable form using CyberChef a free nifty tool which hosts a plethora of tools to encode/decode data. Aptly called, The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis.

The output generated looks a bit cleaner now. It says –

$s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("ANOTHER_LOONG_STRING_R_U_KIDDING_ME"));IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();

There are two takeaways from the above string –

  1. We’ll again have to decode a Base64 String
  2. I am seeing words like Compression/Decompress so maybe we’ll have to decompress the output of this string.

A visually appealing [read shamelessly copy/pasted from the Internet] screen snippet –


Layer 2 – Attack of Compression

Now, we only input the string  H4sIAAAAA..[truncated]..GDQAA into CyberChef and apply these Recipes –

Layer 3 - The Last Beacon

 I am no PowerShell expert and normally we don’t expect IT administrators to be one apart from the common day-to-day administrative tasks. Leafing through the script, there’s literally nothing that stands out to me from a Malware’s perspective. I can’t see a URL, IP, recognizable Port number or any dodgy looking function like func DoEvilStuff() or func DestroyTheResistance() 

What I do see towards the end of the script, is another string of looong characters which might hold some answers –

[Byte[]]$var_code = [System.Convert]::FromBase64String("/OiJAAAAYInlMdJ..ENUFF_IS_ENUFF_I_QUIT..jEwOAA=")

Nevertheless, we’ve come too far just to quit. So let’s put that string back into CyberChef and apply the “From Base64” Recipe again –


The reason we didn’t get a cleaner looking output is because it’s not a script [PowerShell, Batch, JavaScript, Visual Basic Script etc.] but a shell-code. We have seen attackers embed etire PE [Portable Executable], DLL [Dynamic Link Library] files within the script. Back to topic, Wikipedia’s description:

“In hacking, a shellcode is a small piece of code used as the payload in the exploitation of a software vulnerability. It is called "shellcode" because it typically starts a command shell from which the attacker can control the compromised machine, but any piece of code that performs a similar task can be called shellcode.”

Machine A – Bob the Attacker
Machine B – Alice the Victim

starts a command shell – In layman terms, Bob managed to execute a piece of malicious program on Machine B which gave him a pathway to control any/every aspect of it.


  • Bob knew Alice loves cute pictures of dogs so he sent a disguised email with a malicious attachment which read “Have you ever seen a dog play a ukulele? Click here to see!” She clicks on it and Bob gets complete access of Alice’s machine without her knowing.
  • Bob knew Alice is running a very old Windows 7 machine. He exploited a vulnerability in Alice’s OS remotely using the EternalBlue exploit – without any user intervention.

After analyzing the shell-code, we found it to be a part of Cobalt Strike which is threat emulation software. This software helps in security assessments that replicate the tactics and techniques of an advanced adversary in a network. But threat actors often misuse this tool to perform attacks on businesses.

“Beacon is Cobalt Strike's payload to model advanced attackers. Use Beacon to egress[extract data or communicate back from] a network over HTTP, HTTPS, or DNS. You may also limit which hosts egress a network by controlling peer-to-peer Beacons over Windows named pipes. Beacon is flexible and supports asynchronous and interactive communication. Asynchronous communication is low and slow. Beacon will phone home, download its tasks, and go to sleep. Interactive communication happens in real-time.”

There will be times when the IP address isn’t visible using the normal decode process. The above example has been straight-forward however for the sake of demonstration, you may find a similar piece of code just after the shell-code snippet -

[Byte[]]$var_code = [System.Convert]::FromBase64String('38u[Redacted_Chracters_CMjIyMg')

for ($x = 0; $x -lt $var_code.Count; $x++) {

      $var_code[$x] = $var_code[$x] -bxor 35


All you have to do is apply one extra recipe called XOR and you'll see a similar output as below - 

You can also utilize a tool called ScDbg [Shell-dode Debug]

“scdbg is a shellcode analysis application built around the libemu emulation library. When run it will display to the user all of the Windows API the shellcode attempts to call.”

NOTE: As tempting as this may seem, do no save the Shell-code on a business or a production machine. The Endpoint Protection software might flag a detection. 

Followed by –

NOTE: The IPs may differ in the demonstration as I wanted to cover 2 examples here i.e. with/without XOR in the malicious code. 

If we were to go a little further over to the IDArk Side with the shell-code, 

Success! We have the IP address as well as the Port to which the shell-code was calling out to for further instructions. In an active incident, the ability to quickly extract and pass this information on to a customer quickly makes a substantial difference. Now they can monitor/block this IP and the corresponding Port [as part of their Incident Response] to cut off attacker’s access to their assets.

Phew. All this fuss to execute a shell-code directly in memory because if it was dropped on a disk somewhere [packed with dependencies], an analyst would analyze and create signatures for it. Or someone would upload a copy on VirusTotal and the file will immediately be made public.

I want to end this Blog with a publicly available snippet [Courtesy: ] can practice on. Imagine you found a Malicious Service named UigioaCuQxDqfwNx which had the following string as the service executable. If you're able to drill down on the C2 IP, please post it in a safe manner i.e. 192[.]168[.]0[.]100 in the comments! 



Here's a short video demonstration of the actions we can take on a sample encoded string - 

Anyway, I hope you enjoyed reading this as much as I did while putting this blog together. For any questions, feedback or corrections please feel to leave a comment below!

  •  - Thank you, appreciate you taking some time to give your feedback! I followed @mattnotmax  and would definitely check out his Recipes. I was thinking about writing a similar Blog solely around Cobalt Strike and after comments like these, I might speed it up!

  • Thanks for the details, very timely, came across this as well and ended up with the shell code.   What was interesting though is that the threat actor was using FQDN's and different ones on each host where Powershell -nop .... was running and the payloads could be captured.  Secondly also found a very nice CyberChef recipe which I had to slightly modify for my findings, but running your code through this, I also came up with the 149[.]28[.]81[.]19.  The further steps is to move the shell code to Hex and then to dissassemble the last beacon to find more valuable info. if you are that interested to get deeper into this.  @mattnotmax has some nice recipe's to keep you busy.

  • I got the same IP - 149[.]28[.]81[.]19 -

    Thank you Vikas for this really interesting blog and the great work ;)

  • Thanks Yashraj! Brilliant work, that's the correct IP... or is it? ;) Let's wait for some more entries!

  • I think the IP we get from the public snippet is - 149[.]28[.]81[.]19

    Excellent writeup Vikas! Waiting for another one from you. [:)]