Satoshi’s Secret — 100
We are given the Bitcoin testnet transaction hash 23c9470a2269cf6430569afdd3e2e8f35f633b6cdbc34107ddbab932c4146ba3 and we have to find how to spend the output.
The output script is OP_HASH256 64c9e17ec60cd8e074aa24fdb533b3147b651cc18d7c9bcd6b00ef483affc22f OP_EQUAL, so we need to find an input which gives the desired value when double hashed with sha256.
Several possibilities : try to guess the password, bruteforce it, or simply by looking at the transactions of the funding address, find interesting ones coming from custom scripts. And one is the same script, so the flag is in this transaction encoded in hex : 636f696e62617365
Flag : coinbase
Hide and Seek — 200
We are given the mnemonic phrase play fever bullet unlock error palm insect pottery tower torch memory liquid and we need to find a hidden testnet transaction corresponding to this phrase.
A mnemonic phrase can generate a lot of different addresses depending on the chosen derivation path. So we have to find the right one.
It is not that hard because the right derivation path is not exotic, it follows the classic scheme, it’s simply the receiving address of the first account at index 137.
You can type the mnemonic phrase on this well known website, choose Bitcoin Testnet and click on more rows until you find the derivation path : m/44'/1'/0'/0/137 , corresponding to the address : mygH814iJuKrg7tCY2fspCCpxtU3jrzDsd
Flag : 0.00179362
Evil Droid — 300
An android apk of a malware. After decompiling it, we can see in the files Encryption.java and SneakyService.java that the address has been encrypted with AES ECB. The ciphertext and key can be extracted and decoded with the following python code for example.
Flag : 1Ant1MoneyMoneyC1ub823ckj48m429vs3
Daily Double…spend — 400
Once we analyse the json, we can notice that there two different blocks at index 423215, and the second one has a transaction using the same inputs as the first one but with different output addresses. The flag is the id of this transaction.
Tricky Ether — 500
We have to destuct an ethereum contract with a delegate call in a function. I’m actually not an expert at all at smart contracts so I had to learn how to do it. I looked on the blockchain for other contracts that had already been destroyed by other contestants and I understood what I had to do.
The function hackme call the function “0x12345678” of the contract given in argument. I learned that the 4 bytes represent the start of the keccak256 of the function name we want to call. It’s called the function signature. Since this value was not in this database, we have either to bruteforce a good name or we can just use what is called the “fallback function” : the function which is called when the corresponding signature is not in the contract.
So the destruction is done in two steps:
- Deploy a contract with a fallback function calling selfdestruct on an ethereum address you control.
- Call the hackme function with this address and give as argument the contract you deployed.
The contract that I destroyed : 0x30232EE6DDD81d83B81c5B45e30918f1b92E2958
AES Encryption Flaw — 100
The flag has been encrypted with a random key and a random IV with AES in OFB mode. The ciphertext being 16 bytes, it means that in fact the IV has been encrypted and then simply xored with the flag.
Since we are given the encrypted IV, a simple xor of the two hex gives us the flag.
Flag : th1s is sec01234
ECDSA Nonce Reuse — 200
A classic ECDSA bad implementation attack : nonce reuse. Here is my code used to solve it. Don’t forget to hash the messages and that there are 4 possibilities to try.
Flag : 0x128e06938ac462d9
Linkable Payments — 300
A lot of text in this challenge, what is important is that we send coordinates of points of an elliptic curve to a server, the server multiply them by its private key and we can see the result in the log.
The server is vulnerable to an invalid curve attack because it doesn’t check if the points are really on the curve before doing the multiplication.
And all the points sent in the given file have been chosen to have a small prime order which can be bruteforced to find the private key value modulo this prime, and then a final Chinese Remainder Theorem will give us the full private key. What an elegant and clever attack!
Here is my slow python implementation :
And a fast one using the powerful algorithms of Sage:
If you don’t know SageMath, it has a lot of optimized number theory algorithms, like the discrete_log to find the discrete logarithm for groups of small orders. No need to download the whole big package if you don’t want to do heavy calculations, you can just copy paste your code here.
Two things are to be noted in these scripts. In python, I use the bitcoin library which has the same flaw as the server, it doesn’t check if the points are on the curve and add them as if they were. In Sage, it will throw you an error if you do that, so I have to calculate the equation of the new elliptic curve : not that hard to find the new b. And why new b and not new a? Because if you look at the addition formulas on elliptic curves, only the a value is used! So you have to keep the same a but you can change the b and you will have the same results as the server.
Flag : 0xdec1a551f1edc014ba5edefc042019
Schnorrer Signature — 400
We have here a custom signature scheme inspired from Schnorr signature but with a huge vulnerability.
If we analyse the validation equation :
We can choose any value we want for alpha_z and u_n, and it won’t change g, u, nor c. (It would have been way safer to have c = H(m,u_n) instead of H(m,u))
Starting with a random u_n is not good because we will have to solve a discrete logarithm to find alpha_z. But the other way is a simple equation to solve:
Flag (not unique): a2f57a8dda7aaa0ab8d3ea8f1a8ba229e0014f39490c38f2b9474297be761552944d7be847155b44b7931b32e01eece94447076b4392e81da2a2f1f20a2ea984a8764708a392983dfa0daa74a072f5ee654f9755b6caf2a3ea3850d706117310
Forging A Signature — 500
Here we have to forge a signature to create cryptocurrency out of thin air. The way to do it is to find x such as:
It’s normally impossible because h has been randomly chosen, and finding x would be solving a discrete logarithm problem. But here we are given a relation between g and h and we can use it :
(n is the group order of the elliptic curve and inv is the modular inversion)
Now we have x, we can simply use the Schnorr Identification Protocol (with h as base not g) :
Flag : (0x372f3bb24ac2b8cc7825ff9463159663bbe8bb0a4429046ec1fecc877fc4562f4, 0x8ba15dee43a757f32428724800549cbf28e20218d36eb4e7eba656f417d99e23)
I would like to thank Coinbase for this CTF and for the awesome metal mnemonic wallet that I won!