Serious Security: How to cut-and-paste your way to Bitcoin riches

Thanks to Glyn Kennington of SophosLabs for his help with this article.

Let’s say you wanted to vanish into the ether with a whole load of other people’s bitcoins – or, for that matter, a whole load of a whole load of different cryptocurrencies.

You could start a currency exchange, where customers give you money to buy cryptocoins for them, and later on announce that – pof! – all the coins had vanished.

You could hack into someone else’s cryptocoin exchange and loot the database, leaving them to announce – pof! – that all the coins had vanished.

You could announce a brand new cryptocurrency, invite early adopters to invest by handing over existing digital currency and then – pof! – cut and run.

Well, here’s another way – a cryptocurrency crime that can be carried out via the clipboard.

Malware that uses this trick isn’t new, but the sample we’re looking at here is a great reminder of how careful you need to be when you copy and paste text.

Whether it’s cryptocurrency addresses, payment card details, ID numbers or other snippets of personal information, malware that sneakily changes data in the clipboard as you work online can trick you into paying the wrong people.

It’s almost as though you end up stealing from yourself!

How cryptocurrency addresses work

When you send cryptocurrencies such as bitcoins to someone else, there’s a point at which you need to enter a unique identifier that denotes the address of the recipient.

Very greatly simplified, the address is derived from a public encryption key (the sender uses this to denote that the payment is meant for you) for which you have the corresponding private encryption key.

The fact that you have the relevant private key is what establishes you as the current owner of the relevant cryptocoin and allows you to spend it in turn.

You don’t need to prove you hold the private key to receive a cryptocoin to a given address. You only need the private key when you want to sign that cryptocurrency amount over to someone else, i.e. to spend it. Cryptocoins for which the private key has been lost can never be spent – they still exist, but they’re marooned, dead-ends in the chain of ownership that can never be passed on.

Anyone can create a new public/private keypair at any time, in a fraction of a second, thus simultanously generating a new address at which to receive payments, and possessing the needed private key to sign the cryptocoin over to the next owner in the chain.

Here’s how it works for Bitcoin transactions:

  • Generate a good-quality random number (128 bits or more).
  • Use it to generate a 256-bit elliptic curve private key.
  • Extract the corresponding public key.
  • Generate a cryptographic hash of it to serve as this transaction’s identifier.
  • Encode this identifying hash into alphanumeric characters to form a Bitcoin address.

That’s where the curious strings of characters that denote Bitcoin addresses come from – we’ve included a script below demonstrating bulk address generation.

Encoding addresses into letters and digits

There are various formats for cryptocoin addresses.

Ethereum, for example, encodes its 20-byte addresses into hexadecimal characters, so you need two characters for every byte.

This type of string, often called Base16 encoding, is usually preceded by 0x, which is a common programming notation to denote that what follows is in hexadecimal (base 16), giving Ethereum addresses a 42-character text representation like this:


Bitcoin and numerous other currencies use 25-byte addresses.

To encode these addresses more compactly than in hexadecimal, Bitcoin and others use Base58, based on 58 different “digits” consisting of the upper and lower case English letters plus the digits (26+26+10 = 62 choices), but omitting the easily-confused characters ell, EYE, OH and zero (62-4 = 58):

   Base58 character set: abcdefghijk mnopqrstuvwxyzABCDEFGH JKLMN PQRSTUVWXYZ 123456789

For many cryptocurrencies with Base58 address encoding, the first few bits of each address are standardised so that they always encode to the same character, acting as a memory aid like this:

   1NWMWpz1bkksMPobsTK9mSgGppdiH5QFeK  -- Bitcoin 
   36SPv3cTg6SB174c2QRLZ3Tg7TxZfeP9wP  -- Bitcoin 
   DJnpuZ9RafbechwbAxbL9wLFLXYuVoGth5  -- Dogecoin
   LJ3EVYaro3nUqsjBq8yfWnpNCv2e7EhY8b  -- Litecoin
   XEKxPRbEHTd8vxogY132byxbxn6RyQZSWW  -- Dash 
   NA9C3MYMTYzPoPiMUZLLLuzw82wdtYFpnC  -- Namecoin 
   tQ2GpzYLRW4tpn7UJ958hVVDs2dCB3bxmx  -- Zcash
   PQ3YsuyJb7dsfnQDmxn3yNsF2UbNFjUN4   -- Peercoin

We chose the currencies mentioned here because they’re the ones targeted by the malware described below. The addresses shown here are fictitious – we created them directly from a pseudorandom generator instead of formally from a public key.

Using cryptocoin addresses

Loosely speaking, cryptocoin addresses are no more memorable that random strings of letters and numbers, which is almost what they are.

So, in the list above, apart from the tell-tale characters at the start to denote the cryptocurrency concerned, there’s no discernible pattern; no “muscle memory” you can call upon when typing them in; and no easy way to check that you typed correctly other than to read back each character one-by-one.

As a result, the way you usually choose whom to pay is by copying a bitcoin address from a message someone has sent you, or from their web page…

…and pasting it into some sort of payment app or another web page.

In other words, crooks can steal bitcoins without cracking your passwords, reading your local cryptocurrency wallets, copying your private keys, hacking into online currency exchanges, or even having a network connection at all.

All they need is to implant malware that scans your clipboard every so often, watches out for text that looks like a cryptocurrency address, and rewrites it with a similar text string that is an address they generated for themselves.

If you don’t notice the last minute substitution, you might end up paying the cryptocoins out to an imposter – and the anonymity and unregulated nature of crytocurrencies means that the chance of getting your money back is essentially zero.

And, by design, thanks to the lack of a central authority in the cryptocurrency ecosystem, anyone who wants to make a raft of new cryptocoin addresses for use in an attack can do so quickly and easily.

To make 10 bitcoin addresses, for example, you could use the open source tool Bitcoin Explorer (BX) as follows, assuming you’re at a bash command prompt:

$  for i in $(seq 10); do   # 10 times in sequence...
      bx seed |             # Generate pseudorandom bits
      bx ec-new |           # Use this to generate a new Bitcoin-style private key
      bx ec-to-public |     # Get the public key that matches it
      bx ec-to-address      # And then hash-and-Base58-encode it


We’ve messed up the output to invalidate these addresses so they can never be used, whether by mistake or design. The command sequence we used above doesn’t keep the private keys from which the addresses were derived, so that sending funds to these addresses would be a one-way trip consigning the associated bitcoinage to digital oblivion. Valid addresses can receive funds, but without the matching private key, the funds become unspendable – they can never be signed over to anyone else.

Cooking the clipboard

As mentioned above, clipboard-tweaking malware isn’t new, but this sample, blocked by Sophos products as Troj/Agent-AZHF, is an excellent reminder of how easily you can be tricked.

The Agent-AZHF malware is packaged as a DLL, a special sort of Windows program that is usually intended to play a supporting role when it is loaded into other apps, rather than to act as an app in its own right.

However, Windows comes with a built-in utility called RUNDLL32 – a general-purpose wrapper that loads DLLs into memory, for example for testing.

As a result, DLL-based malware can’t be self-contained – it needs a script or a regular program to issue the relevant RUNDLL32 command in the first place.

Nevertheless, crooks sometimes install malware components as DLLs because the name of the running process then shows up as rundll32.exe, allowing the DLL itself to hide in plain sight, as it were:

When Agent-AZHF is loaded for the first time, it copies itself into the AppData folder, using the same name under which it arrived on your hard disk.

It then sets an autorun entry in the Windows registry so that it gets reloaded every time you logon, so that it survives reboots:

Once active, the malware examines the contents of the clipboard four times a second, testing to see if the contents match any of these patterns:

   (^| )[13][a-km-zA-HJ-NP-Z0-9]{26,33}($| )     -- Bitcoin
   (^| )D[a-km-zA-HJ-NP-Z0-9]{33}                -- Dogecoin 
   (^| )L[a-km-zA-HJ-NP-Z0-9]{33}                -- Litecoin
   (^| )X[a-km-zA-HJ-NP-Z0-9]{33}                -- Dash
   (^| )0x[a-fA-F0-9]{40}                        -- Ethereum blockchain 
   (^| )(N|M)[a-km-zA-HJ-NP-Z0-9]{33}($| )       -- Namecoin
   (^| )t[a-km-zA-HJ-NP-Z0-9]{34}($| )           -- Zcash
   (^| )P[a-km-zA-HJ-NP-Z0-9]{33}($| )           -- Peercoin

The patterns above are what’s known as regular expressions (known as REs or regexps), a popular form of string matching toolkit that provides more flexibility than just looking for specific words or numbers.

Don’t worry too much if you aren’t a regular expression expert; all you need to know above is that:

  • (^| ) matches a space or the start of a line.
  • ($| ) matches a space or the end of a line.
  • Characters not in [square brackets] or {squiggly brackets} match themselves.
  • Characters in [squares] match any of the ranges listed.
  • A number in {squiggles} means you need that many repeats of the previous match.
  • Two numbers listed as {min,max} need between min and max repeats.

The first expression, for example, says to look for a 1 or a 3, followed by anywhere from 26 to 33 Base58 characters, with the whole string set off as if it were a word on its own.

The Base58 regexps above are not, in fact, quite right. There are 59 different characters in the ranges specificed inside the [square brackets], including the digit 0. But zero is one of the four alphanumerics (along with I,O and l), that aren’t used in Base58.

If the malware finds a regexp match in the clipboard text, it replaces the matched text with a different address for the same cryptocurrency.

For everything but Bitcoin, the search-and-replace has a single replacement address, presumably one owned by the crooks, but for Bitcoin transactions, the criminals have tried to be a bit more subtle.

The malware includes a list of more than 2,000,000 bitcoin addresses, from 111224... to 1zzzmm..., and tries to find the closest match to the address it’s replacing, presumably to make it less likely that you’ll notice the switch.

Amusingly, it seems there’s a bug in the matching algorithm that means it doesn’t check correctly after the first four characters, so that the malware only ever chooses from about 125,000 of the 2 million entries in the list…

…but it’s easy, nevertheless, to miss the difference when a bitcoin address is rewritten with one that’s at least passingly similar.

Another bug means that if the regular expression matches a cryptocoin address that’s in the middle of a sentence, set off by spaces, the spaces vanish during the substitution:

   BEFORE: A text line with 0x0123456789012345678901234567890123456789 in the middle of it.

                     --- is mis-converted with the spaces chopped out: ---

   AFTER:  A text line with0x1Fd3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7474in the middle of it.

Has it worked?

Here’s a modest silver lining: as far as we can tell, the crooks haven’t made a fortune out of this scam yet.

Firstly, even though we’ve seen a few reports of this malware from numerous countries, it’s still, fortunately, not widespread.

Secondly, it looks as though cryptocoin users are in the habit of double-checking the destination addresses they use when copying-and-pasting digital currency addresses.

We trawled through the blockchain looking at the 125,000 or so bitcoin addresses used in clipboard substitutions by this malware, and found that only 28 had received any incoming payments:

     BTC in                 Address                 US$ [*]
   ----------  ----------------------------------  --------
   0.23000000  16Bxxxxxxxxxxxxxxxxxxxxxxxxxxxx7A1  $1495.00
   0.20000000  1Hpxxxxxxxxxxxxxxxxxxxxxxxxxxxx2YE  $1300.00
   0.09965000  1GnxxxxxxxxxxxxxxxxxxxxxxxxxxxxU1C  $ 647.73
   0.09300000  1Gxxxxxxxxxxxxxxxxxxxxxxxxxxxxxeq8   $604.50
   0.08213189  1HMxxxxxxxxxxxxxxxxxxxxxxxxxxxx9B9   $533.86
   0.06729385  1CPxxxxxxxxxxxxxxxxxxxxxxxxxxxxbcf   $437.41
   0.05761015  14PxxxxxxxxxxxxxxxxxxxxxxxxxxxxSd2   $374.47
   0.03461311  1DNxxxxxxxxxxxxxxxxxxxxxxxxxxxx29X   $224.99
   0.03000000  1RExxxxxxxxxxxxxxxxxxxxxxxxxxxxsF    $195.00
   0.02542576  15LxxxxxxxxxxxxxxxxxxxxxxxxxxxxeNf   $165.27
   0.02481600  1DSxxxxxxxxxxxxxxxxxxxxxxxxxxxxJSk   $161.30
   0.02298632  1P1xxxxxxxxxxxxxxxxxxxxxxxxxxxxUGf   $149.41
   0.01500000  1EcxxxxxxxxxxxxxxxxxxxxxxxxxxxxFQL    $97.50
   0.01012877  1syxxxxxxxxxxxxxxxxxxxxxxxxxxxx6t     $65.84
   0.00983754  15SxxxxxxxxxxxxxxxxxxxxxxxxxxxxCzr    $63.94
   0.00666000  1BMxxxxxxxxxxxxxxxxxxxxxxxxxxxx9yP    $43.29
   0.00384886  19axxxxxxxxxxxxxxxxxxxxxxxxxxxxsvP    $25.02
   0.00357381  1K1xxxxxxxxxxxxxxxxxxxxxxxxxxxxUNH    $23.23
   0.00326711  18nxxxxxxxxxxxxxxxxxxxxxxxxxxxxo5x    $21.24
   0.00306284  15dxxxxxxxxxxxxxxxxxxxxxxxxxxxxNkS    $19.91
   0.00297362  1KtxxxxxxxxxxxxxxxxxxxxxxxxxxxxjzJ    $19.33
   0.00288710  1LBxxxxxxxxxxxxxxxxxxxxxxxxxxxxVdE    $18.77
   0.00215836  15HxxxxxxxxxxxxxxxxxxxxxxxxxxxxaCe    $14.03
   0.00155748  16Cxxxxxxxxxxxxxxxxxxxxxxxxxxxx5fz    $10.12
   0.00043966  13ixxxxxxxxxxxxxxxxxxxxxxxxxxxxEiu     $2.86
   0.00023008  1H2xxxxxxxxxxxxxxxxxxxxxxxxxxxxhGy     $1.50
   0.00002000  1Pbxxxxxxxxxxxxxxxxxxxxxxxxxxxx4dh     $0.13
   0.00000546  112xxxxxxxxxxxxxxxxxxxxxxxxxxxxTim     $0.04
   ----------                                      --------
   1.03317777                                      $6715.66
      ([*] Using 2018-07-05T11:20Z rate of BTC1=USD6500)

On second thoughts, perhaps that’s not a silver lining at all, if we assume that all the transactions showing up in our list are directly due to this malware.

After all, $6715.66 of stolen, largely untracable, unrefundable digital cash is not an amount to be trivialised, even if we’ve grown accustomed to cryptocurrency disasters with millions or hundreds of millions of dollars’ worth of losses.

What to do?

  • When using copy-and-paste for data that’s hard to type, don’t blindly trust the result. Even in the absence of clipboard-hacking malware like this, it’s easy to paste in stale data, especially if you are in a hurry and didn’t hit Ctrl-C (Command-C on a Mac) properly, invisibly leaving the previously copied text in the clipboard instead. This is a serious risk if you paste private data, such as a password, into a data field that’s meant to be public, such as a twitter post!
  • Keep your anti-virus active and up-to-date. DLLs and various other file types sometimes seem harmless because they can’t easily be launched by mistake, given that they need some sort of helper app to load them. But a good anti-virus will identify and dispose of risky DLLs anyway, even if they don’t get loaded immediately.
  • Patch early, patch often. The slower you patch, the greater the chance that crooks will be able to sneak malware onto your network in the first place.
  • Review your email filtering policy. Make sure you have DLL files included on your list of email-borne undesirables.
  • Don’t rely on a network firewall alone to catch data exfiltration. As this example shows, crooks can sneak out your precious cryptocurrency without needing to make any unauthorised network connections of their own. Pasting a bogus recipient address into an intentional online transaction means that the crooks essentially get you to do the exfiltration for them in a legitimate-looking connection.

When it comes to online transactions, check three times, click once…

Note for researchers. This sample was: 48b66dd0­2a336eb0­49a784b3­fd1beb53­12fb8c07­8b3729d4­9e92e3e9­86c98e91.