Making backdoors famous one day at a time
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

8.1 KiB

Verus (VRSC) backdoor

The story of the Verus (https://github.com/veruscoin/VerusCoin) backdoor is fascinating and an example of how users of a cryptocurrency are at the complete whim of the developers of a coin. They must completely trust the developers and anybody who runs the infrastructure or makes binaries/etc. If there is an evil/shady person in that set of people, Very Bad Things Can Happen.

It might be that Mike wants to erase some of the evidence of this, but it's not easy for him, since the code cannot be deleted or the blockchain would not sync correctly. Just in case Mike/VRSC wants to make it harder to find this code or change where it is, I have archived the codebase here: https://git.hush.is/duke/VerusCoin . If any of the links in this document break, they can be viewed in the archived codebase.

High Level Explanation

Here we will explain at a high level what motivated this backdoor and how it works, without delving into code. The lead developer Mike Toutonghi (https://github.com/miketout) mined large amounts of VRSC when it was first created. By some circumstances, he lost access to the wallet.dat file containing the funds. He did not want to relaunch the chain, as it causes a lot of work and confusion for users and mining pools/etc. So he decided to backdoor the code of VRSC, a "friendly" backdoor in his own mind, so he could reclaim his funds.

If you are asking yourself, "what stops this from happening again?" or "What if an evil developer takes over control of VRSC?" or "how can we trust him to not do this again?" then you are understanding the slippery slope that this is.

Mike wrote extremely hard-to-find and hard-to-understand code to backdoor VRSC, that even the lead developer of the upstream code didn't notice. VRSC code is a source code fork of KMD, written by jl777. In the process of code auditing KMD code when merging it into HUSH, I noticed something fishy. Some code that looked very suspicious, but I couldn't immediately understand what it was doing. I asked jl777 directly, as I was a KMD core dev at the time, to see if there was something I didn't understand correctly.

What happened next was a bit shocking. jl777, the lead dev and author of most KMD code, did not know what the code did. It seems he had merged code from VRSC without fully auditing it. Then we both delved into how the code worked, like collecting clues to a mystery. In short time we figured out what the code did.

The code allows the owner of a certain address to spend funds from other addresses ! That is quite a scary thing. What is even sneakier and scarier is that the address never appears on a block explorer! Those two things combined make it quite a sneaky backdoor. Only developers who can read the code would know the backdoor is there, which is exactly what Mike intended.

Mike knew that he did not want anybody else to use his backdoor, only himself. To accomplish this, he found about 700 transactions where his inaccessible addresses received funds. He made his backdoor only able to operate on these past transactions, so the backdoor cannot work for future transactions with unknown transaction id's. Mike did not want to make his backdoor easy to find, so he "encrypted" them (not exactly, he "jumbled" them in a way where it was easy to get the original transaction id, but close enough) and so these transaction id's don't appear in the source code of VRSC. Only the "jumbled" versions of them, which hides the backdoor a bit more.

What stops Mike or a future VRSC developer from removing the restriction of this backdoor only working on those 700 transactions of the past? Absolutely nothing, it could happen at any time. It is trivial to allow the backdoor to work on any transaction and even to make many addresses able to spend funds from other addresses.

When myself and jl777 discovered this, I was quite unhappy about it. jl777 immediately (within minutes) deleted the code from KMD once we realized what it did. The commit that deleted the KMD code is here: 73053ac9d5 . I started to tell the VRSC community and was immediately asked to leave their Discord. Mike then proceeded to rewrite history and tell people it's not a backdoor, it's a "txid reclaimer" and eventually told new users that he asked older users if it was OK to do such a thing. In reality, there was no consent, Mike did what he wanted and informed users later, when his trick was unveiled.

Low-level Explanation

Ok, this section is going to mostly be for developers who maybe don't believe what is said above. Or for enterprising individuals who want to learn more. It's ok if you don't understand everything here, you will likely still get some more understanding out of it.

The VRSC backdoor is spread out across a few different functions and files. This makes it hidden better. It could have been written all in one file in one place, but then it would be very easy to see what is going on.

Here we can see a very important part of the backdoor, the address which is allowed to spend from other addresses:

https://github.com/veruscoin/VerusCoin/blob/master/src/veruslaunch.cpp#L9

This address is RCZyeg6eofQUBKJE5LWuiYkgBPCafheDc8 and if you use https://explorer.verus.io/search you will see that it never appears on the VRSC explorer. Sneaky! This is because this address only needs to sign the transaction where it spends funds from another address. An explorer shows when funds move from one address to another, so the explorer will only show the address funds are coming from and where the funds are going to. Mike created another address where these funds are sent to. That address is not in the source code.

The list of "jumbled" txid's starts here: https://github.com/veruscoin/VerusCoin/blob/master/src/veruslaunch.cpp#L719

The list is not encrypted, it actually just masks each txid with a fixed number, which are listed here: https://github.com/veruscoin/VerusCoin/blob/master/src/veruslaunch.cpp#L11

So the code, to recover the real transaction id, applies the mask to each "jumbled" txid to get the real txid. The purpose of this is so you cannot search the source code for transaction id's AND you cannot look at the source code and look something up on the explorer.

Another important part of the backdoor is the CLaunchMap class defined here: https://github.com/miketout/VerusCoin/blob/master/src/coins.h#L460 . The internals of the code calls the backdoor a LaunchMap in the lmap variable. This line of code: https://github.com/miketout/VerusCoin/blob/master/src/coins.h#L475 is what creates a custom "script" for a transaction:

lmap[hash].scriptPubKey << OP_DUP << OP_HASH160 << address << OP_EQUALVERIFY << OP_CHECKSIG;

Bitcoin Protocol uses something called "Bitcoin Script" language to define transactions and what they do. The above script would not be able to be created via the normal CLI (verus-cli) so it's done manually in the code. The internals of Bitcoin, KMD and VRSC would not normally be able to do this, but Mike defined a new function which does less error checking called GetKeyID_NoCheck() to accomplish this.

The data which the "launch map" returns (the list of transaction id's which can be spent by the special whitelist address listed in source code) is of the type CTransactionExceptionData. The line of code which actually "unjumbles" the transaction id's is at : https://github.com/miketout/VerusCoin/blob/master/src/coins.cpp#L577 where you can see it does:

if ((txData.voutMask & (((uint64_t)1) << (uint64_t)input.prevout.n)) != 0)
{
                return txData.scriptPubKey;
}

the list "mask" for every transaction id is called voutMask and it is bitwise AND'ed with the jumbled tx data to get the real transaction id. In that case, the custom scriptPubKey is returned. If not, then the default happens, which is to only allow an address which owns funds to actually spend them.

Additional Sources

https://nitter.ca/VerusCoin/status/1158931179392794625

https://nitter.ca/MyHushTeam/status/1326146338195558400#m

For reference, jl777 is one of the largest investors of VRSC and Satinder is jl777's paid employee.