Deobfuscating DOSfuscated Scripts
In a recent article, I wanted to easily collect malicious scripts dumped from Office maldocs so I could analyze them. After accumulating dozens of these scripts, I found that most if not all of them employed DOSfuscation to obfuscate their PowerShell content.
I also wrote previously how to deobfuscate this scripts statically and dynamically. In this post I'll show you how to dynamically analyze these scripts so you can quickly get the deobfuscated content.
Have a look at the DOSfuscation source code on GitHub and you'll find a folder called "Samples" with four text files grouped by method -- Concatenated, Reversed, FORcoded and FINcoded. I'll cover some examples from this folder next.
Let me start with a simple one. At the bottom is a "DO %b /c %wZ%". The "DO %b" is "cmd /c" and "%wZ%" is the variable we want to see the contents of. So you just make the change you see.
I paste this to the CMD prompt and let it run. You can see that the deobfuscated content is "net user".
Here's one example where you can delete everything after the pipe which is near the end of the script.
The result is shown at the very bottom.
Here's a reversed script. I just replace the "%TMP:~-8 ... -12,+1%" at the end with "echo".
And "net user" is the result.
In this example, I replace the "call" at the end with "echo" and then I get the variable to the left of the equal sign. I look for the double-exclamation marks and take one of them.
The result is "net user" again.
In this last example, I replace "echo" with "set" and remove the percent signs at the beginning and end. I also remove the pipe up to the closest parenthesis.
And get this result.
Based on the above samples, here are several tips on how you can deobfuscate them in the future.
- Replace "CMD" and "PowerShell" verbs (could be obfuscated) at the end with "echo"
- Find the final variable that holds the deobfuscated content then replace the execution verb with "echo" or "set"
- If you use "set" then get rid of the percent signs (%) before and after the variable name
- A variable name could contain spaces, or more specifically, end with a space so cleaning up the script or extracting the variable name with too little or too much spaces will likely result in failure
- Sometimes you can delete everything after the pipe (|) (but if the script has a double-quote at the end then be sure you keep it)
- Change "call" to "echo" then reference the previously assigned variable with surrounding quotes (!var!)
Now let's move onto live samples that were extracted using CMD Watcher from the previous blog post.
For this sample I first changed the "call" to "echo" and used the variable with the surrounding exclamation marks (!var!) which I've highlighted. I removed some of the content to reduce its size.
Here's the result.
This one looks like it's plain PowerShell but it's being called by CMD. There's an "iex" that I replaced with "echo" (highlighted).
And the result.
This one is similar to the first live sample where I replaced "call" with "echo" and referenced the !var! (highlighted). I think I'll call this is the "bang-var-bang" technique.
Here's the result.
For this sample, I just replaced "call" with "echo".
This is the result.
Finally, I used the bang-var-bang technique (highlighted).
And got this result.
I hope this was helpful.