Welcome to the Shop! Your balance is: 20 1. Buy 2. Sell 3. Exit Choose an option (1-3): 1 You have chosen to buy. Available items and their prices: 1. Humble (5) 2. Yolbby (10) 3. Flag (1000) Select an item (1-3): 3 Enter the quantity to buy: 0 Congratulations, you bought 0 Flag(s) for 0, current balance: 20. CBCTF{4e82e49c-1bcb-4cf9-8576-f6064a1603a7}
defgenSerial() -> list: bucket = [] for i inrange(64): box = [] # individual serial indexes bi = bin(i + 64)[3:] # 0b1[001010] for example bins = list(map(int, bi)) l = 0 r = 43 j = 0 weight = 1.0 while l <= r: m = l + (r - l) // 2 box.append(m) weight = 0.5 * weight + 0.5 * bins[j] if weight <= 0.5: r = m - 1 j += 1 else: l = m + 1 j += 1 bucket.append(box) return bucket
defiterAll(lo:bool) -> list: bucket = [] i = 0 eof = 0 while i < 64: try: bi = bin(i + 64)[3:] if lo: sh = process('./serial') else: sh = remote('training.0rays.club', 10003) sh.recvuntil(b':') sh.sendline(bi.encode()) # send generated serial sh.recvuntil(b'flag:') chars = list(sh.recvline(False).decode()) bucket.append(chars) sh.close() print(f'round {i + 1} passed') i += 1 eof = 0 except EOFError: # sometimes we may lose connection when brute force sh.close() eof += 1 print(f'round {i + 1}, meet eof #{eof}') continue# so we need to reconnect return bucket
defapply(lo): idxs = genSerial() vals = iterAll(lo) table = [] # get index for every char for i inrange(43): for j inrange(64): jmp = False for k inrange(len(idxs[j])): if idxs[j][k] == i: table.append((j, k)) jmp = True break if jmp: break
HEX = [hex(i)[2:] for i inrange(16)] # 01234567890abcdef
defbruteforce(lo:bool, port:int=0): base = 'CBCTF{ - - - - }' match = '25.58%' print(f'starts with flag "{base}" with coverage {match}') base = list(base) for i inrange(32): eof = 0 h = 0 while h < 16: if lo: sh = process('./flag_coverage') else: sh = remote('training.0rays.club', port) base[gapmap[i]] = HEX[h] ret = test(sh, ''.join(base)) sh.close() if ret isNone: # sometimes we lose connection with server eof += 1 continue if ret != match: match = ret # we don't need to store the float value; just compare the str break h += 1 if lo: extraInfo = '' elif eof: extraInfo = f'with {eof} times of eof'# though this time I didn't meet eof else: extraInfo = 'successfully' print(f'digit {i + 1} passed {extraInfo} ({HEX[h]})') print(f'finally we get the flag: {"".join(base)}')
DICT = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_}' LEN = len(DICT)
defbrute(): flag = list('CBCTF{') print('we start brute force with "CBCTF{"') while flag[-1] != '}': i = 0 eof = 0 while i < LEN: try: sh = process('./emulate') sh.send(''.join(flag).encode()) probe = DICT[i] # step by a single char sh.send(probe.encode()) ifnot sh.recvuntil(b'O', timeout=0.25): # if we can't get 'O' in 0.25s then the char is incorrect print(f'digit {len(flag)} is {probe}') # as we may only succeed n times and fail n * LEN times sh.close() # so check failure spend less time (local program runs fast) flag.append(probe) break sh.close() i += 1 except EOFError: # here is kinda strange as when we complete correct flag, we get eof print(f'digit {len(flag)} is {probe}') sh.close() flag.append(probe) break if i == LEN: print(f'DICT is not enough for digit {len(flag)}') # fortunately I didn't meet this case print(f'now we get the flag: {"".join(flag)}')