In this post I want to walk through a process of using the NodeJS REPL (Read, Eval, Print Loop) to safely decode portions of malware during analysis. If you want to follow along at home, the sample I’m working with is here in MalwareBazaar:
Initial File Triage
The tags in MalwareBazaar say the sample is a webshell, but it’s always possible the sample was misclassified. So, let’s approach it with caution and get an idea of its contents using
remnux@remnux:~/cases/wso$ file wso.js wso.js: ASCII text, with very long lines, with no line terminators
It looks like we’re working with a simple text file. Let’s take a peek at the contents using
less. Since all the code inside is on just one or two lines,
head returns all the text by default. Let’s just limit it to the first 100 bytes.
remnux@remnux:~/cases/wso$ head wso.js -c 100 document.documentElement.innerHTML=String.fromCharCode(60, 63, 112, 104, 112, 32, 10, 47, 47, 32, 83
<html> tag in browsers. The
.innerHTML property lets you access the contents of the tag. In this case, the material returned from
String.fromCharCode will be set to the contents of the document HTML tags.
Decoding the Contents
node running in the terminal that is part of VSCode.
In some cases we can copy and paste code directly into the
node interface, but this file is about 95KiB in size. If we try pasting that amount of text into the command line we’re going to wait a long time for the command line to catch up and then execute. I’ve learned this the hard way. Instead, let’s make a JS file we can execute with
node! This will process much faster than pasting a ton of data to the command line.
We can use the
fs.writeFileSync() function to write the output of
String.fromCharCode to a file on disk.
fs = require('fs'); page = String.fromCharCode(60, 63, 112, 104, 112, 32, ... ); fs.writeFileSync('clearpage.txt',page)
Now we can execute
node deobfuscate.js or whatever else your script is named. Afterward, let’s take a look at what kind of file was deobfuscated.
remnux@remnux:~/cases/wso$ node deobfuscate.js remnux@remnux:~/cases/wso$ file clearpage.txt clearpage.txt: PHP script, UTF-8 Unicode text, with very long lines remnux@remnux:~/cases/wso$ head -c 25 clearpage.txt <?php // Shell Mr.Lutfie
Awesome, it looks like we got a PHP file so we can rename it to
Other Ways to Decode
After executing in the console, we can see the page attempt to render in the browser and we can grab the decoded PHP code.
Finally, if you love CyberChef, you can also use it to validate your decoding. Copy all the arguments for
.fromCharCode into CyberChef and bake using the recipe
From Charcode setting the separator to “comma” and base to 10.
console.log("Thanks for reading!")