# Crypto stealing exploit: a JS entrypoint

By [moru](https://paragraph.com/@moruu) · 2024-02-16

---

If you are involved in the blockchain or cryptocurrency space, you might own wallets containing valuable assets. It is important to protect your keys with robust security protocols (hardware wallet or air gapped computer).

Even if you are careful, you may still fall victim to an attack. Here is a demonstration of how such an exploit works.

Step 1: initial contact
-----------------------

After a conversation on LinkedIn, an individual (the attacker) sent me this message:

![LinkedIn message, reported. But that was not very effective.](https://storage.googleapis.com/papyrus_images/371136b531d52e8f0df086ff34c38cb8750dc91bad9d2e038542aadba348a04a.png)

LinkedIn message, reported. But that was not very effective.

The assignment looked fishy. I requested more information, but they refused to give any until I completed their task. At this point, I had no interest in working on this task but I knew I was going to find something _cool_ in this repository.

Step 2: investigation
---------------------

After cloning the repository in a virtual machine, I started looking at every single file carefully. My first assumption was that this project had been compromised by a malicious package (in the **package.json** or **package-lock.json** files). That would be an easy way to trigger an exploit while hiding the payload code. Here is the process:

*   Publish a malware package on [npm](https://www.npmjs.com)
    
*   Add the malware package as a dependency to this project
    
*   Trigger the malware when running the project
    

Unfortunately, I did not find any suspicious package. However, I did find an interesting hint.

![A dependency from the package.json](https://storage.googleapis.com/papyrus_images/7276d33fa2189f52a2ce9bd60785c69445713348a0ad1b268d409d9db4ee6111.png)

A dependency from the package.json

The **package.json** has a dependency to the `fs` (filesystem) package, which is strange since `fs` is a built-in node module: there is no need to install it as a dependency. This was probably a mistake. But it got me thinking, the filesystem is the place to look for private keys or passwords.

A simple search for `fs` in the project revealed what I was looking for.

Step 3: the payload
-------------------

It seems there is a `require(“fs”)` somewhere in this file…

![?](https://storage.googleapis.com/papyrus_images/9225f88e4d27930481a70bece57a8c59808e41d52118c3dbe8a04e42c9ac5acc.png)

?

I did not see it at first, but the first line is just that long. If we scroll a little bit more…

![Bingo!](https://storage.googleapis.com/papyrus_images/56443119300542b163fe473d402b65cd7bb64fc71c2b351026c6233804cf5b30.png)

Bingo!

**Finally!** This appears to be the exploit payload. This could have been innocuous minified code, but only malicious actors would conceal their code this way. Let’s analyze what it does.

Step 4: analysis
----------------

![Some of the exploit code...](https://storage.googleapis.com/papyrus_images/b1491ac4fcd759f1372e310a52e70158d717ecbbb6ccea7d084bec251ed79c09.png)

Some of the exploit code...

As expected, the exploit code is obfuscated but we can still analyze it. Without executing it. To deobfuscate JS code, here are some simple steps we can take:

*   **Pretty print:** use a tool such as prettier to clean up the code. A pretty printer will format the code to reintroduce spaces and indentation where needed, to increase readability.
    
*   **Find the main obfuscating primitives:** in this case, strings are encoded with base64. It is a quite common method to hide variable names or IP adresses.
    
*   **Write a script to replace strings and rename variables:** input\_obfuscated → script → output\_deobfuscated. This allows to perform changes efficiently on the whole payload. The less manual work, the better.
    
*   **Do manual edits in the obfuscated source, if necessary:** For example, to rename variables manually, or to change the formatting. In that case, their obfuscator tends to put multiple statements on the same line (separated by commas). I did manual edits to make the code more readable.
    

After some time working on the code, it was easy to understand how the exploit works. It is triggered when the user runs the application (a Node web server) and their goal is **to steal your private keys, wallets, passwords and more.** Here are the original files for reference: [Obfuscated payload](https://gist.github.com/morukutsu/8a309154164e3574d2563035f858fd72), [Unobfuscated payload](https://gist.github.com/morukutsu/c5d7dd0c41fe561abf16e0e9c53811b4)

Luckily, the obfuscation here was rather simple. They could have employed stronger techniques such as Control-flow flattening or introducing dead code.

And some code snippets from the exploit.

![Dump browser extensions data from popular browsers (Chrome, Brave, Opera...)](https://storage.googleapis.com/papyrus_images/be4249fc641544f7f1bc9412785db7e2ad080182255812d21d74115f51ecf94e.png)

Dump browser extensions data from popular browsers (Chrome, Brave, Opera...)

![Steal your Solana private keys](https://storage.googleapis.com/papyrus_images/0d7f203ab17abc7349e32d34c5442643ceeb323812429d7df718833204a72a2e.png)

Steal your Solana private keys

![Dump your Apple key chain](https://storage.googleapis.com/papyrus_images/1e791938c578eabe404a6de1e05d8dd25a37931a579b33ddec1900925d591fe2.png)

Dump your Apple key chain

![And send all this data back home!](https://storage.googleapis.com/papyrus_images/2f3058e2d9e39d6545c28b3b5e8a30aef1777030d6a1d654e804e89d8e0173cb.png)

And send all this data back home!

This stage of the malware relies on Node to access the victim’s filesystem. Its success depends on whether or not the host gave enough permissions to Node to access restricted directories such as the home directory, and system files. Running this script with elevated privileges probably means game over.

Step 5: going deeper
--------------------

At this point, I had seen enough to be convinced this was an exploit attempt. However there was more: this payload had a second stage that downloaded and ran Python based malware with more elaborate features to steal user credentials.

The second stage downloads a Python program (and even downloads Python if not available on the victim machine!). Below is the full code of the second stage:

![Bootstrap for Python malware](https://storage.googleapis.com/papyrus_images/ca543ac1446294da2b05c145629d6af741647d6c2e28b8997291f634f3935ffd.png)

Bootstrap for Python malware

Again, this is an obfuscated payload but its structure is much simpler. The base64 encoded exploit code is decoded, and then executed. Here’s the decoded version:

![Stage 2, decoded](https://storage.googleapis.com/papyrus_images/f3e4d6724eceb3aa6e8b1439edab4e7c3f783a6636c342e683675c034350b558.png)

Stage 2, decoded

Reference: [2nd stage payload](https://gist.github.com/morukutsu/0e1d440cfd01a77ec869f9b11cc10c6c)

This is a client for downloading two Python based malwares. They are quite long, and analyzing them is out of the scope of this research but here are some features of the malware:

*   Keylogger
    
*   Clipboard logger
    
*   Shell into the target machine: a wildcard to control the target and possibly send even stronger malware
    
*   Stealing passwords/credit cards
    

![Keylogger](https://storage.googleapis.com/papyrus_images/c50041553eebfa7fea750f03abca1fdf5f5f61d7d11c318399e7d7850a3f5aba.png)

Keylogger

![Stealing credit cards](https://storage.googleapis.com/papyrus_images/26fab7cdfc44d10f2a4b8c66e7de4295e1d2f9261c9f456325f600d5e36545b3.png)

Stealing credit cards

Reference: [First](https://gist.github.com/morukutsu/6b8376c10fb9e953c0dd49452a34d343), [Second](https://gist.github.com/morukutsu/31407f3c620c00db6e0b170dba217015)

Closing words
-------------

Working in the blockchain space requires extra caution to safeguard your assets.

This is especially true if you own or earn crypto. Do not run unverified Git repositories. If you must, use a virtual machine.

However, manually inspecting every file we download and run is impractical.

The community has to think about more automatic ways to detect exploits. Or make sure Node is sandboxed properly. That is also why I prefer [Deno](https://deno.com)’s security model, but it is not always practical to use either.

By looking for a fingerprint of the payload on Github, we can see that multiple repositories are infected. Probably forks of a similar exploit attempt.

If you think you have been exploited by this or need more details, you can reach me @moru on Farcaster.

[https://warpcast.com/moru](https://warpcast.com/moru)

Hack safely!

---

*Originally published on [moru](https://paragraph.com/@moruu/crypto-stealing-exploit-a-js-entrypoint)*
