paint-brush
Reversing a NodeJS Malware and Finding its Authorby@thedevopsguy
586 reads
586 reads

Reversing a NodeJS Malware and Finding its Author

by The Devops GuyFebruary 1st, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

A Discord admin recently received a report that someone was trying to get him to download an EXE file. He inspected the binary and found keywords in it. He looked up on Google and Github for those keywords and found the source of the tool on Github to investigate what the hack is doing.

Company Mentioned

Mention Thumbnail
featured image - Reversing a NodeJS Malware and Finding its Author
The Devops Guy HackerNoon profile picture


To give a bit of context, I am a Discord admin on a small server about development, and we recently got a report from one of our users that someone was trying to get him to download an EXE file.


The first thing I did was ask the reporter if he opened the file, to which he answered he did. He told me the program opened a console prompt for a few seconds and then exited. Most of the time, this isn’t good when you have downloaded a file from an untrusted source…

So I grabbed my computer and downloaded the file (I downloaded it in a Linux VM, so if it gets infected in some ways, I can delete the VM). Time to investigate.

Determining the kind of binary

My first idea was to look up what was in this executable. To do so, I used the strings command like this :

> strings file.exe


The strings command finds the printable strings in a binary file. It is helpful to see any strings like URLs or addresses embedded in a file.


This returned gibberish for most of the result, but at some point, I saw NodeRuntime. We can now say it is a NodeJS bundled executable!


In that kind of executables, the sources are always present at the end of the strings output. Let’s take a look at those sources :

function a0_0x47b121(_0x44bb58,_0x4e9d60,_0x355d77,_0x4e9d34,_0x1a193e){return a0_0x1b80(_0x1a193e- -0x1e4,_0x44bb58);


The code looks obfuscated and minified on a very long line…

I applied the following method to understand the logic behind the obfuscated code.

First approach: Discord

I knew that this binary was distributed through Discord DMs, so I looked if the code contained the word discord with grep. Bingo!


Several functions contain the word discord: listDiscords , startDiscord , killDiscord and pwnBetterDiscord . This last function looked promising.


I looked up on Google and Github for pwnBetterDiscord and found the source of the tool: https://github.com/Stanley-GF/PirateStealer.

PirateStealer

We have found the source code that was used in the bundled app. Let’s give it a look.


It steals all the information that it can find from the Discord client by first killing the discord client and patching it with a Javascript payload to exfiltrate private information like Discord credentials and credit cards info via a Discord webhook (an URL where you can POST to send a message to your Discord server).


The author claims that this tool is only for educational purposes, but he also sells premium features and support? That doesn’t seem like a righteous “educational purposes” claim…

Finding the webhook URL from the obfuscated code

The code is filled with many proxy functions that try to obfuscate the access to the main string-obfuscation function. Thanks to the code not being fully obfuscated, we can find webhook=a0_0x78da73(0x331,0x342,0x32c,0x2f1,0x324) . Let’s play a game and extract all the methods needed to decipher this code.


For the sake of brevity, I will rename all the obfuscated functions to fn1 , fn2 … and their params p1 , p2


a0_0x78da73 (let’s call it fn1) takes 5 arguments but it only cares about the first and the last one :

**function** fn1(p1,p2,p3,p4,p5){return fn2(p5 - 0x26a,p1);}

fn2 is more complicated, with initialization vectors and complex rotations, but we can bypass the complexity by calling this function directly. Let’s do that!


I created a new file called find_webhook.js that copies the needed code to run fn2 and console.log(fn2(0x324 — 0x26a, 0x331)), and… we have it! The output is https://ptb.discord.com/api/webhooks/abcdefg/hijklmn (output censored for privacy reasons).

Finding the user of the script

I then used the webhook to send them messages telling them that I knew what they were doing and telling them to DM me with my discord ID, hoping they would answer me. And they did!


From that, no more to say, the discussion was not very productive, but at least I could tell other servers we had in common that the bad guy was also on their server.


I hope this post will encourage people to be more considerate when downloading executables from untrusted sources and will help some others to see how we can reverse NodeJS malwares, which are more and more used nowadays.


If you have any suggestions or comments, do not hesitate to post them in the comment section, and I will try to answer them.


Also, don’t forget to follow as I will continue to publish more advanced topics on this hack and Electron.


Also Published Here