Grand Theft Read.Cash

8 1
Avatar for BigBlockIfTrue
Written by
  4
Came for internet payments, stayed for sound money.
1 week ago

Earlier today, the people behind Read.Cash drafted a proposal for a smart contract allowing password-based wallet recovery. I think this has both positive and negative aspects. I like the general idea of ...

The tools

  • Bitcoin ABC (required, blockchain history not needed)

  • text editor (required)

  • Electron Cash (optional)

  • Mission Impossible theme music (optional)

The plan

Step 1. Use Electron Cash to generate a receiving address for the booty. Upon success, Electron Cash will automatically initiate CashShuffle for the perfect getaway. I generated bitcoincash:qpq9y25eejhx7pdk53eul93r563v68jz4s4stdkf5j. Alternatively, use the wallet within Bitcoin ABC, but then the treasure remains traceable.

Step 2. Bitcoin ABC comes with an optional command-line utility bitcoin-tx to construct transactions. You can find it in the bin directory. Summon its manual:

$ bitcoin-tx -?
Bitcoin ABC bitcoin-tx utility version v0.20.6-unk

Usage:  bitcoin-tx [options] <hex-tx> [commands]  Update hex-encoded bitcoin transaction
or:     bitcoin-tx [options] -create [commands]   Create hex-encoded bitcoin transaction

Options:

  -?
       This help message

  -create
       Create new, empty TX.

  -json
       Select JSON output

  -txid
       Output only the hex-encoded transaction id of the resultant transaction.

Chain selection options:

  -testnet
       Use the test chain

Commands:

  delin=N
       Delete input N from TX

  delout=N
       Delete output N from TX

  in=TXID:VOUT(:SEQUENCE_NUMBER)
       Add input to TX

  locktime=N
       Set TX lock time to N

  nversion=N
       Set TX version to N

  outaddr=VALUE:ADDRESS
       Add address-based output to TX

  outdata=[VALUE:]DATA
       Add data-based output to TX

  outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]
       Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS.
       Optionally add the "S" flag to wrap the output in a
       pay-to-script-hash.

  outpubkey=VALUE:PUBKEY[:FLAGS]
       Add pay-to-pubkey output to TX. Optionally add the "S" flag to wrap the
       output in a pay-to-script-hash.

  outscript=VALUE:SCRIPT[:FLAGS]
       Add raw script output to TX. Optionally add the "S" flag to wrap the
       output in a pay-to-script-hash.

  sign=SIGHASH-FLAGS
       Add zero or more signatures to transaction. This command requires JSON
       registers:prevtxs=JSON object, privatekeys=JSON object. See
       signrawtransactionwithkey docs for format of sighash flags, JSON
       objects.

Register Commands:

  load=NAME:FILENAME
       Load JSON file FILENAME into register NAME

  set=NAME:JSON-STRING
       Set register NAME to given JSON-STRING

Step 3. Figure out what coin you want to steal. In this case, the mission is output 1 (count from zero) of transaction b48e260f36142340cc1652bbc2da5028303e21f469d169393d3b08f234165dfc, worth 0.02290635 BCH.

Step 4. Create the transaction, ignoring the amount of the output for a moment:

$ bitcoin-tx -json -create in=b48e260f36142340cc1652bbc2da5028303e21f469d169393d3b08f234165dfc:1 outaddr=0:qpq9y25eejhx7pdk53eul93r563v68jz4s4stdkf5j
{
    "txid": "d0dc399a668008fa6a0bebc0680ba16d3ca33187fa0ea37adf7a5a367f330dbd",
    "hash": "d0dc399a668008fa6a0bebc0680ba16d3ca33187fa0ea37adf7a5a367f330dbd",
    "version": 2,
    "size": 85,
    "locktime": 0,
    "vin": [
        {
            "txid": "b48e260f36142340cc1652bbc2da5028303e21f469d169393d3b08f234165dfc",
            "vout": 1,
            "scriptSig": {
                "asm": "",
                "hex": ""
            },
            "sequence": 4294967295
        }
    ],
    "vout": [
        {
            "value": 0.00000000,
            "n": 0,
            "scriptPubKey": {
                "asm": "OP_DUP OP_HASH160 40522a99ccae6f05b6a473cf9623a6a2cd1e42ac OP_EQUALVERIFY OP_CHECKSIG",
                "hex": "76a91440522a99ccae6f05b6a473cf9623a6a2cd1e42ac88ac",
                "reqSigs": 1,
                "type": "pubkeyhash",
                "addresses": [
                    "16s6gJN1t7yPZGfzUFvMo9xkFvN7MzjkHH"
                ]
            }
        }
    ],
    "hex": "0200000001fc5d1634f2083b3d3969d169f4213e302850dac2bb5216cc402314360f268eb40100000000ffffffff0100000000000000001976a91440522a99ccae6f05b6a473cf9623a6a2cd1e42ac88ac00000000"
}

Step 5. You see the scriptSig field of the input, the signature script that authorises spending the input, is still missing. Since the coin we're stealing is a Pay-to-Script-Hash (P2SH) coin, the signature script consists of the unhashed P2SH script (b251f93c45baea5c72bae18311c75eccad404291 OP_OVER 'read.cash' OP_EQUAL OP_NIP OP_NIP), preceded by all other input data to this P2SH script itself (again the password 'read.cash'):

             Password length (9) push operation: 09
                                       Password: 726561642e63617368
Unhashed P2SH script length (35) push operation: 23
                           Unhashed P2SH script: 14b251f93c45baea5c72bae18311c75eccad4042917809726561642e63617368877777

Full signature script:

09726561642e636173682314b251f93c45baea5c72bae18311c75eccad4042917809726561642e63617368877777

Step 6. Our signature script is 46 bytes long, or 47 bytes including a 1-byte length indicator prefix (2e). This must replace the 0-byte signature script with 1-byte length indicator (00) in our transaction template. The transaction will therefore grow from 85 bytes to 131 bytes. With the minimum fee rate of 1 sat/b, we thus need to attach a fee of 0.00000131 BCH, so we can claim 0.02290504 BCH for ourselves. Generate a new transaction template accordingly:

$ bitcoin-tx -json -create in=b48e260f36142340cc1652bbc2da5028303e21f469d169393d3b08f234165dfc:1 outaddr=0.02290504:qpq9y25eejhx7pdk53eul93r563v68jz4s4stdkf5j
{
    "txid": "0229cef50d62eff07dd7133ce9db29364c46866b0b46f8437f58bf3e2012318e",
    "hash": "0229cef50d62eff07dd7133ce9db29364c46866b0b46f8437f58bf3e2012318e",
    "version": 2,
    "size": 85,
    "locktime": 0,
    "vin": [
        {
            "txid": "b48e260f36142340cc1652bbc2da5028303e21f469d169393d3b08f234165dfc",
            "vout": 1,
            "scriptSig": {
                "asm": "",
                "hex": ""
            },
            "sequence": 4294967295
        }
    ],
    "vout": [
        {
            "value": 0.02290504,
            "n": 0,
            "scriptPubKey": {
                "asm": "OP_DUP OP_HASH160 40522a99ccae6f05b6a473cf9623a6a2cd1e42ac OP_EQUALVERIFY OP_CHECKSIG",
                "hex": "76a91440522a99ccae6f05b6a473cf9623a6a2cd1e42ac88ac",
                "reqSigs": 1,
                "type": "pubkeyhash",
                "addresses": [
                    "16s6gJN1t7yPZGfzUFvMo9xkFvN7MzjkHH"
                ]
            }
        }
    ],
    "hex": "0200000001fc5d1634f2083b3d3969d169f4213e302850dac2bb5216cc402314360f268eb40100000000ffffffff0148f32200000000001976a91440522a99ccae6f05b6a473cf9623a6a2cd1e42ac88ac00000000"
}

Step 7. To complete the transaction, the signature script must be inserted into the transaction template manually. To do so, copy and paste the hexadecimal representation of the transaction into a text editor. Use the transaction format documentation to decode it and find the right place for inserting the signature:

                    Version number (2): 02000000
        Number of inputs (1) as varint: 01
                    Parent transaction: fc5d1634f2083b3d3969d169f4213e302850dac2bb5216cc402314360f268eb4
   Parent transaction output index (1): 01000000
 Signature script length (0) as varint: 00
              Remainder of transaction: ffffffff0148f32200000000001976a91440522a99ccae6f05b6a473cf9623a6a2cd1e42ac88ac00000000

Step 8. Replace the zero-length signature script with the actual signature script constructed earlier:

                    Version number (2): 02000000
        Number of inputs (1) as varint: 01
                    Parent transaction: fc5d1634f2083b3d3969d169f4213e302850dac2bb5216cc402314360f268eb4
   Parent transaction output index (1): 01000000
Signature script length (46) as varint: 2e
                      Signature script: 09726561642e636173682314b251f93c45baea5c72bae18311c75eccad4042917809726561642e63617368877777
              Remainder of transaction: ffffffff0148f32200000000001976a91440522a99ccae6f05b6a473cf9623a6a2cd1e42ac88ac00000000

Full transaction: 0200000001fc5d1634f2083b3d3969d169f4213e302850dac2bb5216cc402314360f268eb4010000002e09726561642e636173682314b251f93c45baea5c72bae18311c75eccad4042917809726561642e63617368877777ffffffff0148f32200000000001976a91440522a99ccae6f05b6a473cf9623a6a2cd1e42ac88ac00000000

Step 9. Verify that the resulting transaction looks alright:

$ bitcoin-tx -json 0200000001fc5d1634f2083b3d3969d169f4213e302850dac2bb5216cc402314360f268eb4010000002e09726561642e636173682314b251f93c45baea5c72bae18311c75eccad4042917809726561642e63617368877777ffffffff0148f32200000000001976a91440522a99ccae6f05b6a473cf9623a6a2cd1e42ac88ac00000000
{
    "txid": "b73ad30dcba9ed29512ae2c8ea23d6c6bfd8786042e1347938b96e1b296b1f2c",
    "hash": "b73ad30dcba9ed29512ae2c8ea23d6c6bfd8786042e1347938b96e1b296b1f2c",
    "version": 2,
    "size": 131,
    "locktime": 0,
    "vin": [
        {
            "txid": "b48e260f36142340cc1652bbc2da5028303e21f469d169393d3b08f234165dfc",
            "vout": 1,
            "scriptSig": {
                "asm": "726561642e63617368 14b251f93c45baea5c72bae18311c75eccad4042917809726561642e63617368877777",
                "hex": "09726561642e636173682314b251f93c45baea5c72bae18311c75eccad4042917809726561642e63617368877777"
            },
            "sequence": 4294967295
        }
    ],
    "vout": [
        {
            "value": 0.02290504,
            "n": 0,
            "scriptPubKey": {
                "asm": "OP_DUP OP_HASH160 40522a99ccae6f05b6a473cf9623a6a2cd1e42ac OP_EQUALVERIFY OP_CHECKSIG",
                "hex": "76a91440522a99ccae6f05b6a473cf9623a6a2cd1e42ac88ac",
                "reqSigs": 1,
                "type": "pubkeyhash",
                "addresses": [
                    "16s6gJN1t7yPZGfzUFvMo9xkFvN7MzjkHH"
                ]
            }
        }
    ],
    "hex": "0200000001fc5d1634f2083b3d3969d169f4213e302850dac2bb5216cc402314360f268eb4010000002e09726561642e636173682314b251f93c45baea5c72bae18311c75eccad4042917809726561642e63617368877777ffffffff0148f32200000000001976a91440522a99ccae6f05b6a473cf9623a6a2cd1e42ac88ac00000000"
}

Step 10. Start the Bitcoin ABC node. Open the debug window via the help menu and go to the console tab. Read the scammer warning and laugh evilly, because this time you are the criminal. Then, summon the command list:

$ help

== Blockchain ==
(...)

== Control ==
(...)

== Generating ==
(...)

== Mining ==
(...)

== Network ==
(...)

== Rawtransactions ==
combinepsbt ["psbt",...]
combinerawtransaction ["hexstring",...]
converttopsbt "hexstring" ( permitsigdata )
createpsbt [{"txid":"id","vout":n},...] [{"address":amount},{"data":"hex"},...] ( locktime )
createrawtransaction [{"txid":"id","vout":n},...] [{"address":amount},{"data":"hex"},...] ( locktime )
decodepsbt "psbt"
decoderawtransaction "hexstring"
decodescript "hexstring"
finalizepsbt "psbt" ( extract )
fundrawtransaction "hexstring" ( options )
getrawtransaction "txid" ( verbose "blockhash" )
sendrawtransaction "hexstring" ( allowhighfees )
signrawtransactionwithkey "hexstring" ["privatekey1",...] ( [{"txid":"id","vout":n,"scriptPubKey":"hex","redeemScript":"hex"},...] sighashtype )
testmempoolaccept ["rawtxs"] ( allowhighfees )

== Util ==
(...)

== Wallet ==
(...)

Step 11. Find the transaction broadcast command sendrawtransaction and look up how it works:

$ help sendrawtransaction

sendrawtransaction "hexstring" ( allowhighfees )

Submits raw transaction (serialized, hex-encoded) to local node and network.

Also see createrawtransaction and signrawtransactionwithkey calls.

Arguments:
1. "hexstring"    (string, required) The hex string of the raw transaction)
2. allowhighfees    (boolean, optional, default=false) Allow high fees

Result:
"hex"             (string) The transaction hash in hex

Examples:

Create a transaction
> bitcoin-cli createrawtransaction "[{\"txid\" : \"mytxid\",\"vout\":0}]" "{\"myaddress\":0.01}"
Sign the transaction, and get back the hex
> bitcoin-cli signrawtransactionwithwallet "myhex"

Send the transaction (signed hex)
> bitcoin-cli sendrawtransaction "signedhex"

As a json rpc call
> curl --user myusername --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "sendrawtransaction", "params": ["signedhex"] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/

Step 12. Now go for it. Don't let your dreams be dreams. Join the dark side. Commit the crime:

$ sendrawtransaction 0200000001fc5d1634f2083b3d3969d169f4213e302850dac2bb5216cc402314360f268eb4010000002e09726561642e636173682314b251f93c45baea5c72bae18311c75eccad4042917809726561642e63617368877777ffffffff0148f32200000000001976a91440522a99ccae6f05b6a473cf9623a6a2cd1e42ac88ac00000000

Alea iacta est. If the heist succeeds, Electron Cash will quickly detect an incoming transaction. But since the transaction has no cryptographic signature, the booty can still be stolen by a miner even more evil than you - until the transaction is confirmed. Electron Cash will then CashShuffle the proceeds to make it untraceable. Just make sure to avoid spending the shuffled coins together.

Proof of success

Message: All Read.cash's $5 are belong to BigBlockIfTrue!

Address: qpq9y25eejhx7pdk53eul93r563v68jz4s4stdkf5j

Signature: IDuoVZb/0Qm+TAaKMdvf4wbR0WvW/iq1zwN3VwYqf4xSDVY9kxfN3cu3pJ2rnbufmvbjntP9T+eAQ1suPPZIHDw=

$ 7.10
$ 5.00 from @Read.Cash
$ 1.00 from @btcfork
$ 1.00 from @molecular
$ 0.10 from Anonymous user(s)
A
Avatar for BigBlockIfTrue
Written by
  4
Came for internet payments, stayed for sound money.
1 week ago
Enjoyed this article?  Earn Bitcoin Cash by sharing it! Explain
...and you will also help the author collect more tips.
About us Rules What is Bitcoin Cash? Roadmap Affiliate program Get sponsors Self-host
E-mail (PGP key) Reddit