flag format: 0xV01D{...} giải rồi viết write up ch...
Creato il: 18 maggio 2026
Risposto usando GPT-5.5 Thinking da Chat01
Creato il: 18 maggio 2026
Risposto usando GPT-5.5 Thinking da Chat01
flag format: 0xV01D{...}
giải rồi viết write up chi tiết kèm lệnh + script đã dùng
pythonfrom pathlib import Path p=Path('/mnt/data/challenge.txt') data=p.read_bytes() len(data), data[:200], data[-200:] (6238, b'In the beginning, there was nothing.\nThen nothing whispered: let there be layers upon layers.\nSome say the answer lies within the silence between words.\nOthers believe it hides in plain sight, staring', b"n0t_qu1te_lol}\nOr perhaps it was never here at all.\nThe void speaks in whispers you cannot hear with your ears.\nListen with your tools. All of them. Every. Single. One.\nGood luck. You'll need it. \xf0\x9f\x98\x88")
pythontext=p.read_text('utf-8') len(text), text[:500] (2779, "In the beginning, there was nothing.\nThen nothing whispered: let there be layers upon layers.\nSome say the answer lies within the silence between words.\nOthers believe it hides in plain sight, staring back at you.\nThe number 677 means everything. Or maybe nothing. Who knows?\nDecoded message: dGhpcyBpcyBub3QgdGhlIHdheSBsb2wgdHJ5IGhhcmRlcg==\nSeek and you shall find. Or maybe you won't. HAHAHAHA.\nThe wise man once said: U NEED TO DO 677.\u200b\u200b\u200c\u200c\u200b\u200b\u200c\u200c\u200d\u200b\u200b\u200c\u200c\u200b\u200c\u200b\u200c\u200d\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200c\u200d\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200b\u200d\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200c\u200d\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200b\u200d\u200b\u200b\u200c\u200c\u200b\u200b\u200c\u200b")
pythonfrom collections import Counter cnt=Counter(text) for ch,c in cnt.items(): if ord(ch)>127 or ord(ch)<32 and ch not in '\n\t': print(hex(ord(ch)), repr(ch), c) print("newlines", cnt['\n']) # extract zero-width chars U+200B ZWSP, U+200C ZWNJ, U+200D ZWJ etc zws=''.join(ch for ch in text if ch in '\u200b\u200c\u200d\ufeff\u2060') len(zws), Counter(zws) (1728, Counter({'\u200b': 808, '\u200c': 728, '\u200d': 192}))
pythonseq=zws groups=seq.split('\u200d') len(groups), Counter(len(g) for g in groups), groups[:5], groups[-3:] (193, Counter({8: 192, 0: 1}), ['\u200b\u200b\u200c\u200c\u200b\u200b\u200c\u200c', '\u200b\u200b\u200c\u200c\u200b\u200c\u200b\u200c', '\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200c', '\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200b', '\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200c'], ['\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200b', '\u200b\u200c\u200c\u200b\u200c\u200c\u200c\u200c', ''])
pythondef decode_bits(map0): # map dict {zwsp:'0', zwnj:'1'} etc bits=[] for g in groups: if len(g)==8: bits.append(''.join(map0[ch] for ch in g)) bs=bytes(int(b,2) for b in bits) return bs for mapping in [ {'\u200b':'0','\u200c':'1'}, {'\u200b':'1','\u200c':'0'} ]: bs=decode_bits(mapping) print(mapping, bs[:100], bs) try: print(bs.decode('utf-8')) except Exception as e: print(e)
pythons=decode_bits({'\u200b':'0','\u200c':'1'}).decode() len(s), s (192, '35101021a8r432431nisli89itp1304654316e1t4785939f5xr2l87h8887n1nii25630wrfujy8rlir05m57242l14l9918740y9rc9920v9e35ws39066l107907e0027493ok1g06k69y0ma7rjw8s3n82d618957r3kgit871931mfv2h7wp6m1f10o')
pythonimport string, re, base64, binascii, codecs, math, itertools, collections alph=string.digits+string.ascii_lowercase def caesar_base36(s, shift): return ''.join(alph[(alph.index(c)-shift)%36] if c in alph else c for c in s) for sh in [677%36, -(677%36), 1, -1, 26, -26, 29, 7]: print(sh, caesar_base36(s, sh)[:100])
pythonfor variant in ['std']: try: b=base64.b64decode(s, validate=True) print(len(b), b[:100]) print(b.decode('utf-8','replace')[:200]) except Exception as e: print("b64 err",e) # base32? base36 decode? hex? try: print(bytes.fromhex(s[:100])) except Exception as e: print("hex err", e)
pythonlines=text.splitlines() for i,line in enumerate(lines,1): # remove zero-width? print(i, repr(line[-20:]), "last", repr(line[-1]), hex(ord(line[-1]))) print("lines", len(lines)) print("last chars no hidden?", ''.join(line[-1] for line in lines if line)) # last visible char ignoring zero width? def last_visible(line): for ch in reversed(line): if ch not in '\u200b\u200c\u200d': return ch key=''.join(last_visible(line) for line in lines if line) key '....?=..)))))}}}...😈'
pythonimport re, string, base64, binascii, itertools, math def rail_fence_decrypt(cipher, rails): if rails == 1: return cipher # pattern of rail indices pattern = list(range(rails)) + list(range(rails-2,0,-1)) rail_indices = [pattern[i % len(pattern)] for i in range(len(cipher))] counts = [rail_indices.count(r) for r in range(rails)] rails_str=[] idx=0 for c in counts: rails_str.append(list(cipher[idx:idx+c])); idx+=c pos=[0]*rails out=[] for r in rail_indices: out.append(rails_str[r][pos[r]]); pos[r]+=1 return ''.join(out) def rail_fence_encrypt(plain, rails): if rails==1: return plain rails_arr=['']*rails pattern=list(range(rails))+list(range(rails-2,0,-1)) for i,ch in enumerate(plain): rails_arr[pattern[i%len(pattern)]]+=ch return ''.join(rails_arr) for r in range(2,21): dec=rail_fence_decrypt(s,r) enc=rail_fence_encrypt(s,r) for name,t in [('dec',dec),('enc',enc)]: if re.search(r'0xV01D|flag|0xv01d|v01d', t, re.I): print("found", r,name,t) print("r",r, "dec", dec[:80], "enc", enc[:80])
pythonb=base64.b64decode(s) def score_ascii(bs): return sum(32<=x<127 or x in (9,10,13) for x in bs)/len(bs) best=[] for k in range(256): x=bytes(c^k for c in b) best.append((score_ascii(x), k, x[:100])) best=sorted(best, reverse=True)[:10] for sc,k,x in best: print(sc,k,x) print(x.decode('latin1')[:120])
pythontry: from Crypto.Cipher import AES from Crypto.Util.Padding import unpad print("pycryptodome ok") except Exception as e: print("no crypto", e)
pythontry: from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend print("cryptography ok") except Exception as e: print("no cryptography", e)
pythonfrom cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives import padding, hashes from cryptography.hazmat.backends import default_backend from hashlib import md5, sha256, sha1 def aes_decrypt(data,key,mode='ECB',iv=None): if mode=='ECB': cipher=Cipher(algorithms.AES(key), modes.ECB()) elif mode=='CBC': cipher=Cipher(algorithms.AES(key), modes.CBC(iv or bytes(16))) dec=cipher.decryptor() return dec.update(data)+dec.finalize() def try_keys(): candidates=[] bases=[ b"677", b"676", b"0xV01D", b"0xv01d", b"0xV01D Team", b"0xV01DTeam", b"U NEED TO DO 677", b"U NEED TO DO 677 HAHAHAHA", b"HAHAHAHA", b"last character of each line", b"trust me bro", b"what you see is not what you get", b"What You See Is Not What You Get", b"nothing", b"void", b"silence", ] # strings derived last chars for ks in [ ''.join(line[-1] for line in lines if line).encode('utf-8','ignore'), ''.join(last_visible(line) for line in lines if line).encode('utf-8','ignore')]: bases.append(ks) for base in bases: variants=[base] variants.append((base*16)[:16]) variants.append((base*24)[:24]) variants.append((base*32)[:32]) variants.append(md5(base).digest()) variants.append(sha256(base).digest()) variants.append(sha1(base).digest()[:16]) variants.append(base.ljust(16,b'\0')[:16]) variants.append(base.ljust(24,b'\0')[:24]) variants.append(base.ljust(32,b'\0')[:32]) for key in variants: if len(key) in (16,24,32): for mode in ['ECB','CBC']: for iv in [bytes(16), md5(base).digest(), b'677'*5+b'6'] if mode=='CBC' else [None]: try: pt=aes_decrypt(b,key,mode,iv) sc=score_ascii(pt) if sc>0.7 or b'0xV01D' in pt or b'flag' in pt.lower(): candidates.append((sc, base, len(key), mode, iv, pt[:200])) except Exception as e: pass return sorted(candidates, reverse=True, key=lambda x:x[0]) cands=try_keys() len(cands) 0
pythonkeys=[ ''.join(line[-1] for line in lines if line).encode('utf-8'), ''.join(last_visible(line) for line in lines if line).encode('utf-8'), b"677", b"HAHAHAHA", b"U NEED TO DO 677", b"0xV01D"] for data_name,data in [('b64bytes', b), ('hidden_ascii', s.encode())]: print('---',data_name) for key in keys: x=bytes(c ^ key[i%len(key)] for i,c in enumerate(data)) print("key",key[:40], "score", score_ascii(x), x[:120]) if b'0xV01D' in x or b'flag' in x.lower(): print("FOUND",x)
pythonsb=s.encode() def english_score(bs): text=''.join(chr(b) if 32<=b<127 else ' ' for b in bs).lower() common=' etaoinshrdl{}_0123456789xv' return sum(text.count(c)*w for w,c in enumerate(common[::-1],1)) - 10*sum(b<32 or b>126 for b in bs) best=[] for k in range(256): x=bytes(c^k for c in sb) if all(32<=c<127 or c in (10,13,9) for c in x): best.append((english_score(x), k, x[:200])) for score,k,x in sorted(best, reverse=True)[:20]: print(score,k,repr(x[:120]))
pythonfrom collections import Counter cnt=Counter(s) print(cnt) print(len(set(s))) for k,v in cnt.most_common(): print(k,v)
pythonidx=text.find('\u200b') print(idx, text[:idx][-100:], len(text[:idx])) print("byte idx", data.find('\xe2\x80\x8b'.encode() if False else b'\xe2\x80\x8b'))
pythonprint(data.find(b'\xe2\x80\x8b'), data.find(b'\xe2\x80\x8c'), data.find(b'\xe2\x80\x8d')) print(len(text[:idx].encode()))
pythonprint(data[430:480]) print([hex(b) for b in data[438:450]]) for ch in text[438:450]: print(hex(ord(ch)), ch.encode())
pythonraw=Path('/mnt/data/challenge.txt').read_bytes() print(len(raw), raw[430:480], raw.find(b'\xe2\x80\x8b')) print(text.encode('utf-8')[430:480])
pythonfor mapping in [ {'\u200b':'0','\u200c':'1'}, {'\u200b':'1','\u200c':'0'}]: for rev in [False, True]: chars=[] for g in groups: if len(g)==8: bits=''.join(mapping[ch] for ch in g) if rev: bits=bits[::-1] chars.append(int(bits,2)) bs=bytes(chars) print(mapping, "rev",rev, bs[:80], score_ascii(bs)) try: print(bs.decode('utf-8')[:200]) except Exception as e: print("decode err")
pythondef shift_digits_letters(s, key): out=[] for i,c in enumerate(s): k=int(key[i%len(key)]) if c.isdigit(): out.append(str((int(c)-k)%10)) elif c.isalpha(): out.append(chr((ord(c)-97-k)%26+97)) else: out.append(c) return ''.join(out) print(shift_digits_letters(s,'677')[:200]) print(shift_digits_letters(s,'677')) # Add instead def shift_add(s, key): out=[] for i,c in enumerate(s): k=int(key[i%len(key)]) if c.isdigit(): out.append(str((int(c)+k)%10)) elif c.isalpha(): out.append(chr((ord(c)-97+k)%26+97)) else: out.append(c) return ''.join(out) print(shift_add(s,'677')[:200])
pythondef caesar_letters(s, shift): out=[] for c in s: if c.islower(): out.append(chr((ord(c)-97-shift)%26+97)) elif c.isupper(): out.append(chr((ord(c)-65-shift)%26+65)) else: out.append(c) return ''.join(out) for sh in [1,-1,677%26,-677%26,13,5,-5,7,-7]: print(sh, caesar_letters(s, sh)[:120])
pythondef caesar_printable(s, shift): out='' for c in s: o=ord(c) if 32<=o<=126: out+=chr((o-32-shift)%95+32) else: out+=c return out for sh in [677%95, -677%95, 677%36, -677%36]: print(sh, repr(caesar_printable(s,sh)[:120]))
pythonfor w in [8,16,24,32,48,64]: print("w",w) for i in range(0,len(s),w): print(s[i:i+w]) print()
pythondef columns_read(s,width): rows=[s[i:i+width] for i in range(0,len(s),width)] return ''.join(''.join(row[c] for row in rows if c<len(row)) for c in range(width)) for w in range(2,50): out=columns_read(s,w) if '0x' in out or '0xv' in out.lower() or 'flag' in out.lower() or 'v01' in out.lower(): print(w,out) # inspect common widths for w in [8,12,16,24,32]: print("width",w, columns_read(s,w)[:200])
pythonfor step in range(2,50): for off in range(step): t=s[off::step] if '0x' in t.lower() or 'v01' in t.lower() or 'flag' in t.lower() or '{' in t: print(step,off,t)
pythonn=int(s,36) bs=n.to_bytes((n.bit_length()+7)//8,'big') len(bs), bs[:100], score_ascii(bs) (124, b'"rK\xa7\xc7I\xd6\xbd\xe0\x8b\x9a)No\xefT`\xa9\xc2\x967`;<\xc5\x8a\x03\xda\x1eX\x8e\xbdH\x91\x0f\xc7\xa2\xae*#\xff;j\xdf\xa5I\xae\xe9\xca\xeaQ\xfcDGj\xae\x14Y\x0b\x95\xff\x053J\x1b~<"\xad\x7f\xffz\x91\x0bw\x0c\x05\x83\xd0\xe1\xe6w\x91Z4\x11.1\xbc\xa5\xc7iG\xd2~=\x9e\xa6\xc5\xbc', 0.3951612903225806)
pythonchars=['\u200b','\u200c','\u200d'] for perm in itertools.permutations('012'): mp=dict(zip(chars,perm)) trits=''.join(mp[ch] for ch in zws) for width in range(3,13): vals=[] ok=True for i in range(0,len(trits)-width+1,width): val=int(trits[i:i+width],3) if val>255: ok=False break vals.append(val) if ok: bs=bytes(vals) sc=score_ascii(bs) if sc>0.85 or b'0x' in bs or b'flag' in bs.lower(): print("perm",perm,"width",width,"len",len(bs),"score",sc, bs[:200])
pythonfor perm in itertools.permutations('012'): mp=dict(zip(chars,perm)) trits=''.join(mp[ch] for ch in zws) for width in [5]: vals=[int(trits[i:i+width],3) for i in range(0,len(trits)-width+1,width)] bs=bytes(vals) sc=score_ascii(bs) if sc>0.5: print("perm",perm,"score",sc,bs[:200]) print(bs.decode('latin1')[:200])
pythondef rot47(text, n=47): out='' for c in text: o=ord(c) if 33 <= o <= 126: out += chr(33 + ((o-33+n) % 94)) else: out += c return out for n in [47, 677%94, -677%94, 13, 19, -19]: print(n, repr(rot47(s,n)[:120]))
pythonalph='0123456789abcdefghijklmnopqrstuvwxyz' def vigenere_base36(s,key,enc=False): out=[] for i,c in enumerate(s): if c in alph: k=alph.index(key[i%len(key)]) idx=alph.index(c) out.append(alph[(idx + k if enc else idx-k)%len(alph)]) else: out.append(c) return ''.join(out) for k in ['677','u','void','0xv01d','hahaha']: print(k, vigenere_base36(s,k)[:120]) print(k, vigenere_base36(s,k,enc=True)[:120])
pythonfor step in [2,3,4,5,6,7]: print("step",step) for off in range(step): print(off, s[off::step][:100]) print()
pythonletters=''.join(c for c in s if c.isalpha()) digits=''.join(c for c in s if c.isdigit()) len(letters), letters, len(digits), digits[:200] (70, 'arnisliitpetfxrlhnniiwrfujyrlirmllyrcvewsleokgkymarjwsndrkgitmfvhwpmfo', 122, '35101021843243189130465431614785939528788871256308055724214991874099920935390661079070027493106690783826189573871931276110')
pythonletters=''.join(c for c in s if c.isalpha()) digits=''.join(c for c in s if c.isdigit()) print(letters) for sh in range(26): t=caesar_letters(letters, sh) if any(word in t for word in ['flag','the','you','try','void','this']): print("caesar",sh,t) print("rail letters") for r in range(2,15): dec=rail_fence_decrypt(letters,r) if any(w in dec for w in ['flag','the','you','try','void','this','xv']): print(r, dec) print(r, dec[:100])
pythondigits=''.join(c for c in s if c.isdigit()) print(len(digits), digits) # parse decimal ASCII maybe 2/3 digits pairs=[int(digits[i:i+2]) for i in range(0,len(digits)-1,2)] print(pairs[:50], bytes([x for x in pairs if x<256])[:50]) # 3-digit parse trip=[int(digits[i:i+3]) for i in range(0,len(digits)-2,3)] print(trip[:30], ''.join(chr(x) if 32<=x<127 else '?' for x in trip[:50])) # apply with ascii from possible [32-126] greedy segmentation?
pythonruns=re.findall(r'\d+|[a-z]+', s) [(r, len(r)) for r in runs], len(runs) ([('35101021', 8), ('a', 1), ('8', 1), ('r', 1), ('432431', 6), ('nisli', 5), ('89', 2), ('itp', 3), ('1304654316', 10), ('e', 1), ('1', 1), ('t', 1), ('4785939', 7), ('f', 1), ('5', 1), ('xr', 2), ('2', 1), ('l', 1), ('87', 2), ('h', 1), ('8887', 4), ('n', 1), ('1', 1), ('nii', 3), ('25630', 5), ('wrfujy', 6), ('8', 1), ('rlir', 4), ('05', 2), ('m', 1), ('57242', 5), ('l', 1), ('14', 2), ('l', 1), ('9918740', 7), ('y', 1), ('9', 1), ('rc', 2), ('9920', 4), ('v', 1), ('9', 1), ('e', 1), ('35', 2), ('ws', 2), ('39066', 5), ('l', 1), ('107907', 6), ('e', 1), ('0027493', 7), ('ok', 2), ('1', 1), ('g', 1), ('06', 2), ('k', 1), ('69', 2), ('y', 1), ('0', 1), ('ma', 2), ('7', 1), ('rjw', 3), ('8', 1), ('s', 1), ('3', 1), ('n', 1), ('82', 2), ('d', 1), ('618957', 6), ('r', 1), ('3', 1), ('kgit', 4), ('871931', 6), ('mfv', 3), ('2', 1), ('h', 1), ('7', 1), ('wp', 2), ('6', 1), ('m', 1), ('1', 1), ('f', 1), ('10', 2), ('o', 1)], 82)
pythonbb=base64.b64decode(s) print(len(bb), bb.hex()) # entropy, bytes distribution print(Counter(bb).most_common(10))
python# Generate possible key strings from line ends; test AES both modes, XOR combos line_last_variants={} for ignore_hidden in [False, True]: for include_emoji in [True, False]: chars=[] for line in lines: if not line: continue ch=last_visible(line) if ignore_hidden else line[-1] if not include_emoji and ord(ch)>127: continue chars.append(ch) name=f"lastvis{ignore_hidden}_emoji{include_emoji}" line_last_variants[name]=''.join(chars) print(name, repr(''.join(chars)), len(''.join(chars)), len(''.join(chars).encode())) # subsets for name,keystr in line_last_variants.items(): print(name, keystr.encode())
pythonfrom itertools import combinations def try_aes_with_keys(keys): outs=[] for desc,key in keys: keyb=key if isinstance(key,bytes) else key.encode() for k in set([keyb[:16], keyb[-16:], keyb[:24], keyb[-24:], keyb[:32], keyb[-32:], md5(keyb).digest(), sha256(keyb).digest(), sha1(keyb).digest()[:16]]): if len(k) not in (16,24,32): continue for mode in ['ECB','CBC']: ivs=[None] if mode=='ECB' else [bytes(16), keyb[:16].ljust(16,b'\0'), keyb[-16:].rjust(16,b'\0'), md5(keyb).digest()] for iv in ivs: try: pt=aes_decrypt(bb,k,mode,iv) # try unpad pts=[pt] try: (10, [(0.4166666666666667, 'lastvisFalse_emojiFalse', b'M\x13\xc1;\x07<b\xeb\xf8[\xbd\xb0\xa8\x1b\xba\xb3d$\x9f\xb7\x02A\x0f\x9e\x8fi\xcb\nRC\xda\xd0', 'CBC', b'!v\x19\x91Ng\xaf\xa3\x89<\xa9\x02\x8f\xe3\x95\x85', b'\xe3\x06.V\xd1\xe5Ls0\x10\xbe\xb6\xae\x13$\xbbdv\xbea|\xb9!\x13\xfa\\c\x91\xc1\x96\x9aq\xc7 I<%\xd4Q\x98\x80A\xf8\xb2\x00\xe5\xde\xe9p\xe6G\xe7g\xa0\x9f\x89Q\xfaO\xde\xad\x1b\xca{Q\x84 C\x97\x88\xa2\xce\xb96\xb4\x96g.\xaa\xbe\xe6\x1f.K2\x1eR.\xfb\xca\xe4)%~\xc4\x19"\x0f_F!\x91\xb9\xca\x05\xe2\xb3q\x1c\x86\xae\xffiCn&>%\x89\x14\x82\xd1h\xa8\x0f\x002\xc4\xe49v\x81J\x81,\x1b\x14*\x81\\\x17\x8f\x08D'), (0.4097222222222222, 'lastvisTrue_emojiFalse', b'.?=..)))))}}}...', 'CBC', b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'\xe6\xeb\xf3\xb4\xd6t.\xa8\xd2\xbe4\xfa\x0fa=\x1b\x11&\xee\xaaH\xc5\r5\xfd1dL\xde}\xa26\xdd\x07\x86h\x9e1\xc5\xb5\x8b\x124\x02\xe4\\ND\xc3\xe6\xea"\xefm\xf3\xadkl\xf2\xdf\xd8\xe2\xdbu\x1e\x94s\xf8\xeaY}\x0e\xfe\x1b>\xba6BSU\xe8eh\xcc\xc9"\r&\x00\xaba\xb5\x90R\xca\x9e\xf9\x8a\xce\x82\x91\xe7\x87\xef\x1e\x8d\x16tc\xf5\xee>bn\xcdCk\xe2\x03Yl\xb8\xa8\x8dTRyXF\x1a\x8c"9\xd4H\xbf\xb4\xf2\xa1\xcd>\xcc\x0bk'), (0.4027777777777778, 'lastvisFalse_emojiFalse', b'....?=.)))))}}}.', 'ECB', None, b"# \xf0\xe8o\xc8\xbaH\xce\x00e\xf8r\x00\x98\xdd\x870g.\xf7\x06)0\xbc\x0c\xe2\x9d}eW\xc6\x1d/\x1d\x84\xf4T\x97\x9f\x8a\x9b\xb8\\\xa7\xe3\xa2W\xc1\x05\x11\x8f)7\xff\x90\x96o\xe5[\xceIP\x04\xbbn|3\x88WY\xcd~\x8c\x01\x1a9'\xd4H^\xbd\x88\x1c_\x02\xc4\x83\x83\x87\xf4\x1eZ<YqSw\x08E\x1a\x949.\xb5\x0fD3\xfbg\xb0[\x1a\x99\xde\xfc\xdd \xe1d\x03\x99\x80\x15\xd2\x9c\x0c\xf7\x1bd\x9f\xb4g\x17\xdf<\x16j\xe3ZX[\xf8;"), (0.3680555555555556, 'lastvisTrue_emojiTrue', b'\x8b\xe7.f\x1a\xa1\xca%F\xc4\xcbYU\x89f\xf8', 'CBC', b'\xa7\x85\xf7\xf3:\x10\xedh\xbf\x89\x83+\xb2YC]', b",\xdf\xcf\x87\xc5\xee.\x88\x83;\xf9\x06\x86\x8c\xa9\x83L\xe4\x13%\xbc\xb0\xd0\x9f\x92\nN\xcb\xff+\xd0\xa6e*\x93\xd8{?\xae!n\x90\xdcC\xc4\xcf\xa6\x92A\xa2\xecp2h\x18S\xb9\xa7t\x19\x93\x8aA\x15\xd9-\xe8\x14\xad\xb6\xd4\xc2\x06\xaec&A\xd6\xb1<\xccjw~'Y]6\xbe6\x133\xd6\x84F\x9dj\xc7\xbb\xf93\xe7\xbc\x92B\x0e\x07\xb5XHZ8\x04\x9c\x90\xef\xeb\xb7^_\x84\xddh\xa4\xe2.\xdf}R4\xadK\xa7\x92\x80\xf8\x04\xb8\xb3\xf8\x19\x05{\xcf"), (0.3611111111111111, 'lastvisFalse_emojiTrue_punctstrip', b"\xe3\xb0\xc4B\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99o\xb9$'\xaeA\xe4d\x9b\x93L\xa4\x95\x99\x1bxR\xb8U", 'ECB', None, b'"Z3$Ew\xe9\x0e\x8b^D\x87\xef\xf7\xb5l~\xce.G\x18\xbd\xa2\xea\xc7\xba\x1c x\x00x\x13W\xfe\xda\xe3v`D~\xeb0\xa6\xa4\x05\x9aj\xf67j\x91k\x8e\x17\xa9\x93\xddq|\t\x86\x84\xd3\x03\x16\xael\xb7p\x03\xe9\xe3\xa46\xcf\x07=\x1a\x1b\x13\x9d\xf0Ns\xa06\xf3 \xdc\x08\xd2Q\x1d(\x97\xc7\xf0\xba\xdf\x8dk[\xff\xf9\x9f\x87\xe8X\x83\x1d\x97lu\xf0\xf9\xe7mTz\x84\xa4\xbb\x93\xf7l\xedPZo{\xae\xc4\xa2\xb0\xc3\x9c\xf2\xfb\x86\xf1T\xa5\xaf\xae')])
pythonbits=''.join('0' if ch=='\u200b' else '1' if ch=='\u200c' else '' for ch in zws) print(len(bits)) for width in [5,6,7,8]: for start in range(width): vals=[int(bits[i:i+width],2) for i in range(start, len(bits)-width+1, width)] # map 5-bit to a-z (0=a or 1=a), 7/8 ascii if width==5: for offset in [0,1]: txt=''.join(chr(v+ord('a')-offset) if 0+offset<=v<=25+offset else '?' for v in vals) if any(w in txt for w in ['flag','void','the','you','xv']): print("w5",start,offset,txt[:300]) else: bs=bytes(v for v in vals if 0<=v<256) sc=score_ascii(bs) if sc>0.7 or b'0x' in bs or b'flag' in bs.lower(): print("width",width,"start",start,"score",sc,bs[:200], bs.decode('latin1')[:200])
pythontexts5=[] for start in range(5): vals=[int(bits[i:i+5],2) for i in range(start, len(bits)-5+1, 5)] for offset in [0,1]: txt=''.join(chr(v+ord('a')-offset) if 0+offset<=v<=25+offset else '?' for v in vals) texts5.append((start,offset,txt)) print("start",start,"offset",offset,"len",len(txt),txt[:200]) # Try Caesar shifts for words for sh in range(26): ca=caesar_letters(txt.replace('?',''), sh) if 'flag' in ca or 'the' in ca or 'you' in ca or 'void' in ca: print(" caesar",sh,ca[:200])
python# Generate candidate phrases/substrings from visible text excluding hidden zero widths visible=''.join(ch for ch in text if ch not in '\u200b\u200c\u200d') # collect words and phrases tokens=re.findall(r'[A-Za-z0-9_{}xV]+', visible) cands=set() for tok in tokens: cands.add(tok) cands.add(tok.lower()) cands.add(tok.upper()) # ngrams up to 5 tokens for ngram in range(2,8): for i in range(len(tokens)-ngram+1): phrase=' '.join(tokens[i:i+ngram]) cands.add(phrase); cands.add(phrase.lower()); cands.add(phrase.upper()) phrase2='_'.join(tokens[i:i+ngram]) cands.add(phrase2); cands.add(phrase2.lower()) # exact lines/after colon for line in visible.splitlines(): cands.add(line.strip()); cands.add(line.strip().lower()) if ':' in line: cands.add(line.split(':',1)[1].strip()) # plus punctuation variants around 677 for c in ['677','0677','677.','677 HAHAHAHA','U NEED TO DO 677.','U NEED TO DO 677','U_NEED_TO_DO_677','doneedtodo677','do677','DO677','do 677','DO 677','6776776776776776','6776776776776777','HAHAHAHA','HAHAHAHA.']: cands.add(c); cands.add(c.lower()) print(len(cands)) # Try AES keys from candidates direct if len 16/24/32, md5, sha, repeats, ljust with zeros/spaces outs=[] for cand in cands: base=cand.encode() variants=set() for L in [16,24,32]: if len(base)>=L: variants.add(base[:L]); variants.add(base[-L:]) variants.add(base.ljust(L,b'\0')[:L]); variants.add(base.ljust(L,b' ')[:L]) variants.add((base*((L//len(base))+1))[:L] if len(base)>0 else b'') variants.add(md5(base).digest()) variants.add(sha256(base).digest()) variants.add(sha1(base).digest()[:16]) for key in variants: if len(key) not in (16,24,32): continue for mode in ['ECB','CBC']: ivs=[None] if mode=='ECB' else [bytes(16), md5(base).digest(), sha256(base).digest()[:16], base[:16].ljust(16,b'\0'), base[:16].ljust(16,b' ')] for iv in ivs: try: pt=aes_decrypt(bb,key,mode,iv) # unpad if possible pts=[pt] pad=pt[-1] if pad<=16 and pad>0 and pt.endswith(bytes([pad])*pad): pts.append(pt[:-pad]) for ptt in pts: sc=score_ascii(ptt) # English score stricter low=ptt.lower() if b'0xv01d' in low or b'flag' in low or b'{' in ptt or sc>0.8: outs.append((sc,cand,key,mode,iv,ptt[:300])) except Exception: pass print("outs",len(outs)) for item in sorted(outs, reverse=True, key=lambda x:x[0])[:30]: print("score",item[0],"cand",repr(item[1]),"key",item[2],"mode",item[3],"iv",item[4],"pt",item[5])
pythonvisible=''.join(ch for ch in text if ch not in '\u200b\u200c\u200d') print(len(visible), len(text), len(zws), len(visible.encode()), len(raw)) print(Counter(ch for ch in visible if ch!='\n').most_common(20)) print(len(raw)-3*len(zws), len(raw))
pythonCounter(letters) Counter({'r': 8, 'i': 7, 'l': 6, 'n': 4, 'f': 4, 'w': 4, 'm': 4, 's': 3, 't': 3, 'e': 3, 'y': 3, 'k': 3, 'a': 2, 'p': 2, 'h': 2, 'j': 2, 'v': 2, 'o': 2, 'g': 2, 'x': 1, 'u': 1, 'c': 1, 'd': 1})
pythondef transforms_basic(x): outs=[] # original/reverse for name,t in [('orig',x),('rev',x[::-1])]: outs.append((name,t)) for r in range(2,min(30,len(x))): outs.append((name+f'_raildec{r}', rail_fence_decrypt(t,r))) outs.append((name+f'_railenc{r}', rail_fence_encrypt(t,r))) for w in range(2,len(x)): if len(x)%w==0 or w<20: outs.append((name+f'_col{w}', columns_read(t,w))) return outs matches=[] for name,t in transforms_basic(letters): for sh in range(26): ca=caesar_letters(t,sh) low=ca.lower() if any(word in low for word in ['flag','final','real','this','the','you','void']): matches.append((name,sh,ca)) len(matches) 33
pythonfor name,sh,ca in matches[:100]: print(name, "shift", sh, ca[:200])
pythonimport os, glob, pathlib glob.glob('/usr/share/dict/*')[:10] ['/usr/share/dict/README.select-wordlist']
pythontry: import wordfreq print("wordfreq ok") except Exception as e: print(e) try: import wordninja print("wordninja ok") except Exception as e: print(e)
pythondef take_steps(s, pattern, start=0): i=start; out='' pi=0 while 0<=i<len(s): out += s[i] i += pattern[pi%len(pattern)] pi+=1 return out for objname,obj in [('s',s),('letters',letters),('visible',visible)]: print('---',objname) for start in range(min(10,len(obj))): out=take_steps(obj,[6,7,7],start) if any(w in out.lower() for w in ['flag','0x','v01','real','you','the']): print(start,out[:200]) # print(start,out[:80])
pythonimport math math.gcd(677,192), 677%192 (1, 101)
pythondef cyclic_step(s, step, start=0): n=len(s); out=[]; i=start; seen=set() for _ in range(n): out.append(s[i]) i=(i+step)%n return ''.join(out) for step in [677, 101, -677, pow(677,-1,len(s)) if math.gcd(677,len(s))==1 else None]: if step is None: continue print("step", step, "mod", step%len(s)) for start in range(0, min(len(s),20)): out=cyclic_step(s,step,start) if '0x' in out.lower() or 'v01' in out.lower() or 'flag' in out.lower() or 'the' in out.lower() or 'you' in out.lower(): print("start",start,out[:200]) print(cyclic_step(s,step,0)[:120]) print("inv", pow(677,-1,len(s)))
pythonfor bitseq_name,bitseq in [('bits_no_sep',bits)]: n=len(bitseq) print(n, math.gcd(677,n)) for direction in [677,-677,pow(677,-1,n)]: if math.gcd(direction,n)!=1: continue for start in [0]+list(range(1,8)): perm=''.join(bitseq[(start+i*direction)%n] for i in range(n)) for revbits in [False, True]: bs=bytes(int((perm[i:i+8][::-1] if revbits else perm[i:i+8]),2) for i in range(0,n,8)) sc=score_ascii(bs) if sc>0.8 or b'0x' in bs or b'flag' in bs.lower(): print("dir",direction,"start",start,"rev",revbits,"score",sc,bs[:200]) try: print(bs.decode())
pythondef decode_zws_sequence(seq): gr=seq.split('\u200d') if all(len(g)==8 for g in gr if g) and len([g for g in gr if g])>0: try: return bytes(int(''.join('0' if ch=='\u200b' else '1' for ch in g),2) for g in gr if len(g)==8) except: return b'' return b'' n=len(zws) print(n, math.gcd(677,n)) for step in [677,-677, pow(677,-1,n)]: print("step",step, step%n) for start in range(9): perm=''.join(zws[(start+i*step)%n] for i in range(n)) bs=decode_zws_sequence(perm) if bs: sc=score_ascii(bs) if sc>0.8 or b'0x' in bs or b'flag' in bs.lower(): print("split", start, len(bs), sc, bs[:200])
pythonimport random def unshuffle_from_seed(cipher, seed): n=len(cipher) perm=list(range(n)) random.Random(seed).shuffle(perm) # if c[i] = p[perm[i]] after shuffle list? Actually random.shuffle on list of plaintext yields shuffled[i]=plaintext[perm[i]] p=['']*n for i,orig_idx in enumerate(perm): p[orig_idx]=cipher[i] return ''.join(p) def shuffle_order_read(cipher, seed): n=len(cipher) perm=list(range(n)) random.Random(seed).shuffle(perm) # maybe c[perm[i]]=p[i] p=['']*n for i,idx in enumerate(perm): p[i]=cipher[idx] return ''.join(p) for objname,obj in [('s',s),('letters',letters),('bits',bits)]: for func in [unshuffle_from_seed, shuffle_order_read]: out=func(obj,677) if objname=='bits': bs=bytes(int(out[i:i+8],2) for i in range(0,len(out)-7,8)) print(objname,func.__name__, score_ascii(bs), bs[:100]) else: print(objname,func.__name__, out[:120]) if any(w in out.lower() for w in ['flag','0x','v01','you','the','real']): print("match")
pythonout=shuffle_order_read(s,677) for w in ['flag','0x','v01','you','the','real']: print(w, out.lower().find(w)) print(out)
pythonbase36bs=bs # from earlier int base36 for key in [b'677', b'\x06\x07\x07', b'0xV01D', b'HAHAHAHA']: x=bytes(c^key[i%len(key)] for i,c in enumerate(base36bs)) print(key, score_ascii(x), x[:100]) try: print(x.decode('utf-8')[:200]) except: pass # single byte best best=[] for k in range(256): x=bytes(c^k for c in base36bs) if b'0x' in x or b'flag' in x.lower() or score_ascii(x)>0.75: best.append((score_ascii(x),k,x[:100])) print(best[:10], len(best))
pythonbin01=''.join(c for c in s if c in '01') len(bin01), bin01[:200] (32, '10101110111001100010000100111110')
pythonb01=bytes(int(bin01[i:i+8],2) for i in range(0,len(bin01),8)) b01, b01.decode('latin1'), b01.hex() (b'\xae\xe6!>', '®æ!>', 'aee6213e')
pythonfor inv in [False,True]: bits2=''.join(('1' if c=='0' else '0') if inv else c for c in bin01) for rev in [False, True]: b01=bytes(int((bits2[i:i+8][::-1] if rev else bits2[i:i+8]),2) for i in range(0,len(bits2),8)) print(inv,rev,b01,b01.hex(),score_ascii(b01))
pythonhexchars=''.join(c for c in s if c in '0123456789abcdef') len(hexchars), hexchars[:200] (133, '35101021a8432431891304654316e14785939f52878887125630f805572421499187409c99209e3539066107907e0027493106690a78382d6189573871931f2761f10')
pythonfor off in [0,1]: hx=hexchars[off:] if len(hx)%2: hx=hx[:-1] bs2=bytes.fromhex(hx) print(off,len(bs2),score_ascii(bs2),bs2[:100]) print(bs2.decode('latin1')[:100])
pythonleet_map=str.maketrans({'0':'o','1':'l','2':'z','3':'e','4':'a','5':'s','6':'g','7':'t','8':'b','9':'g'}) leet=s.translate(leet_map) print(leet[:200]) # maybe looks like english? apply rail/caesar? for name,t in [('leet',leet),('leetrev',leet[::-1])]: for r in range(2,20): dec=rail_fence_decrypt(t,r) if any(w in dec for w in ['flag','this','the','you','real','void']): print(name,r,dec[:200])
pythonwords=['the','flag','real','this','you','found','finally','void','hidden','zero','width','not','get','see'] best=[] for base_name,base in [('s',s),('leet',leet),('letters',letters),('leet_letters',''.join(c for c in leet if c.isalpha()))]: for name,t in transforms_basic(base): for sh in range(26): ca=caesar_letters(t,sh) low=ca.lower() count=sum(low.count(w)*len(w) for w in words) if count>0: best.append((count,base_name,name,sh,ca[:300])) for item in sorted(best, reverse=True)[:50]: print(item[0], item[1], item[2], item[3], item[4])
pythonr5=rail_fence_decrypt(s,5) print(len(r5), r5) print("letters:", ''.join(c for c in r5 if c.isalpha())) print("digits:", ''.join(c for c in r5 if c.isdigit())) print("leet:", r5.translate(leet_map)) print("only letters leet:", ''.join(c for c in r5.translate(leet_map) if c.isalpha())) # Does r5 contain flag if digits mapped? for key in ['677']: pass
pythonfor label,t in [('s',s),('r5dec',r5),('r5enc',rail_fence_encrypt(s,5))]: try: b64=base64.b64decode(t, validate=True) print(label, len(b64), score_ascii(b64), b64[:80], b64.hex()[:100]) # Try zlib/gzip? for name,func in []: pass except Exception as e: print(label,e)
pythonfor tname,t in [('s',s),('rev',s[::-1])]: for r in range(2,10): for op,tt in [('dec',rail_fence_decrypt(t,r)),('enc',rail_fence_encrypt(t,r))]: # Check prefixes/contains for flag after leet map, letters, base64? le=tt.translate(leet_map) if 'flag' in le or 'flg' in tt or 'iflg' in tt or 'flag' in tt: print(tname,r,op, tt[:100], le[:100])
pythonfor objname,obj in [('r5',r5),('r5letters',''.join(c for c in r5 if c.isalpha())),('r5leet',r5.translate(leet_map))]: print('---',objname) for step in range(2,10): for off in range(step): t=obj[off::step] if any(w in t.lower() for w in ['flag','0x','v01','the','you','real','void']): print("step",step,"off",off,t[:150])
pythonb_r5=base64.b64decode(r5) for key in keys+[b"677",b"HAHAHAHA"]: x=bytes(c^key[i%len(key)] for i,c in enumerate(b_r5)) sc=score_ascii(x) if sc>0.7 or b'0x' in x or b'flag' in x.lower(): print(key,sc,x[:200]) # single byte XOR best=[] for k in range(256): x=bytes(c^k for c in b_r5) sc=score_ascii(x) if sc>0.75 or b'0x' in x or b'flag' in x.lower(): best.append((sc,k,x[:100])) print("single",sorted(best, reverse=True)[:5])
pythonb_r5=base64.b64decode(r5) keylist=[b"677",b"HAHAHAHA",b"0xV01D",b"U NEED TO DO 677"] for keystr in line_last_variants.values(): keylist.append(keystr.encode('utf-8')) for key in keylist: x=bytes(c^key[i%len(key)] for i,c in enumerate(b_r5)) sc=score_ascii(x) if sc>0.55 or b'0x' in x or b'flag' in x.lower(): print(key,sc,x[:120]) # single byte XOR best=[] for k in range(256): x=bytes(c^k for c in b_r5) sc=score_ascii(x) if sc>0.55 or b'0x' in x or b'flag' in x.lower(): best.append((sc,k,x[:100])) print("single",sorted(best, reverse=True)[:10])
pythonfor dataname,dat in [('s',s.encode()),('r5',r5.encode())]: print('---',dataname) for key in keylist: x=bytes(c^key[i%len(key)] for i,c in enumerate(dat)) sc=score_ascii(x) if sc>0.8 or b'0x' in x or b'flag' in x.lower(): print(key,sc,x[:200]) print(x.decode('latin1')[:200]) # single best=[] for k in range(256): x=bytes(c^k for c in dat) if all(32<=c<127 for c in x): if b'flag' in x.lower() or b'0x' in x or score_ascii(x)>0.95: best.append((score_ascii(x),k,x[:150])) print(sorted(best, reverse=True)[:5])
pythonxorH=bytes(c^ord('H') for c in r5.encode()).decode('latin1') print(xorH) for n in range(1,94): t=rot47(xorH,n) if 'flag' in t.lower() or '0x' in t.lower() or 'the' in t.lower() or 'you' in t.lower(): print(n,t[:200]) # Maybe Ascii85/base85 decode? import base64 for funcname,func in [('a85',base64.a85decode),('b85',base64.b85decode)]: try: out=func(xorH.encode(), adobe=False, ignorechars=b' \n\t\r\v') print(funcname,len(out),score_ascii(out),out[:100]) except Exception as e: print(funcname,e)
pythontry: out=base64.b85decode(xorH.encode()) print(len(out),score_ascii(out),out[:100]) except Exception as e: print(e)
pythonMORSE = { '.-':'A','-...':'B','-.-.':'C','-..':'D','.':'E','..-.':'F','--.':'G','....':'H','..':'I', '.---':'J','-.-':'K','.-..':'L','--':'M','-.':'N','---':'O','.--.':'P','--.-':'Q','.-.':'R', '...':'S','-':'T','..-':'U','...-':'V','.--':'W','-..-':'X','-.--':'Y','--..':'Z', '-----':'0','.----':'1','..---':'2','...--':'3','....-':'4','.....':'5','-....':'6','--...':'7','---..':'8','----.':'9' } def morse_decode(seq): # slash / separator char, spaces too toks=re.split(r'[ /]+', seq.strip()) return ''.join(MORSE.get(tok,'?') for tok in toks if tok) for dataname,dat in [('s',s.encode()),('r5',r5.encode())]: print('---',dataname) for k in range(32,127): x=bytes(c^k for c in dat).decode('latin1') mor=''.join(ch if ch in '.-/' else ' ' for ch in x) dec=morse_decode(mor) if any(w in dec.lower() for w in ['flag','the','you','void']) or '0XV01D' in dec.upper(): print("key",k,chr(k), "dec",dec[:200],"morse snippet",mor[:100]) # repeated key last chars? maybe for key in [b"HAHAHAHA", b"H", b"677"]: x=bytes(c^key[i%len(key)] for i,c in enumerate(dat)).decode('latin1') mor=''.join(ch if ch in '.-/' else ' ' for ch in x) print("repkey",key, "morse",mor[:120], "dec",morse_decode(mor)[:100])
pythonfrom collections import deque def to_bytes(x): if isinstance(x, bytes): return x return x.encode('latin1','ignore') def to_str(x): if isinstance(x, str): return x try: return x.decode('latin1') except: return x.decode('utf-8','ignore') def is_interesting(x): b=to_bytes(x) low=b.lower() return b'0xv01d' in low or b'flag' in low or b'void' in low def preview(x): s2=to_str(x) return repr(s2[:200]) keys_b=[b'H',b'HAHAHAHA',b'677',b'U NEED TO DO 677',b'0xV01D'] for keystr in line_last_variants.values(): keys_b.append(keystr.encode('utf-8')) def transforms_state(x): outs=[] data=to_bytes(x) st=to_str(x) # rail (144, 1362015)
pythontmp=rail_fence_encrypt(s,5) out=rail_fence_decrypt(tmp,10) out=rail_fence_encrypt(out,4) out=rail_fence_encrypt(out,2) out=rail_fence_decrypt(out,4) print(out) print(len(out)) print(out.translate(leet_map)) print('letters', ''.join(c for c in out if c.isalpha())) print('digits', ''.join(c for c in out if c.isdigit()))
pythondef letters_after_digit(s, digit=None, before=False): out='' for i,c in enumerate(s): if c.isalpha(): prev=s[i-1] if i>0 else '' nxt=s[i+1] if i+1<len(s) else '' if digit is None and prev.isdigit(): out+=c elif digit is not None and prev==str(digit): out+=c return out for dataname,dat in [('s',s),('r5',r5)]: print("----",dataname) for d in range(10): t=letters_after_digit(dat,d) print(d,len(t),t) print("after any",letters_after_digit(dat,None)) # letters before digit d for d in range(10): t=''.join(c for i,c in enumerate(dat[:-1]) if c.isalpha() and
pythondef take_offset_by_digits(s, use_zero=False): out='' for i,c in enumerate(s): if c.isdigit(): d=int(c) if d==0 and not use_zero: continue j=i+d if j<len(s): out+=s[j] return out for dataname,dat in [('s',s),('r5',r5)]: for use_zero in [False,True]: out=take_offset_by_digits(dat,use_zero) print(dataname,use_zero,len(out),out[:200]) print('letters only', ''.join(c for c in out if c.isalpha())[:200]) if 'flag' in out.lower() or '0x' in out.lower(): print('match') # take before offset out='' for i,c in enumerate(dat): if c.isdigit(): d=int(c); j=i-d if j
pythonimport shutil, subprocess, os, sys, pkgutil, importlib.util print(shutil.which('ciphey'), shutil.which('cyberchef'), shutil.which('hashid')) mods=['ciphey','pycipher','cryptography','Crypto','z3','sympy'] for m in mods: print(m, importlib.util.find_spec(m))
pythonCounter(xorH).most_common() [('y', 17), ('x', 15), ('q', 15), ('{', 13), ('p', 13), ('\x7f', 12), ('z', 10), ('}', 9), ('|', 9), ('~', 9), (':', 8), ('!', 7), ('$', 6), ('.', 4), ('%', 4), ('?', 4), ('&', 4), ('<', 3), ('1', 3), ('-', 3), ('#', 3), (';', 3), ('/', 2), ('8', 2), ('"', 2), ("'", 2), (')', 2), ('>', 2), (' ', 2), ('=', 1), ('0', 1), ('+', 1), (',', 1)]
pythons_xorH=bytes(c^ord('H') for c in s.encode()).decode('latin1') for r in range(2,20): for op,t in [('dec',rail_fence_decrypt(s_xorH,r)),('enc',rail_fence_encrypt(s_xorH,r))]: if any(w in t.lower() for w in ['flag','0x','v01','the','you']): print(r,op,t[:200])
pythonfor r in [5,2,3,4,6,7,8,10]: for op,bitperm in [('dec',rail_fence_decrypt(bits,r)),('enc',rail_fence_encrypt(bits,r))]: for rev in [False, True]: bs=bytes(int((bitperm[i:i+8][::-1] if rev else bitperm[i:i+8]),2) for i in range(0,len(bitperm),8)) if score_ascii(bs)>0.8 or b'flag' in bs.lower() or b'0x' in bs: print(r,op,rev,score_ascii(bs),bs[:200]) try: print(bs.decode()) except: pass
pythonraw_lines=raw.splitlines() raw_last=bytes(line[-1] for line in raw_lines if line) raw_last_noemoji=bytes(line[-1] for line in raw_lines if line and line[-1]<128) print(raw_last, len(raw_last), raw_last.hex()) print(raw_last_noemoji, len(raw_last_noemoji)) key_candidates=[raw_last, raw_last_noemoji, raw_last[:16], raw_last[-16:], raw_last_noemoji[:16], raw_last_noemoji[-16:]] # test AES with direct/raw/hash for s and r5 b64 bytes def test_aes_bytes(data, key_candidates): for kb in key_candidates: variants=set() for L in [16,24,32]: if len(kb)>=L: variants.add(kb[:L]); variants.add(kb[-L:]) variants.add(kb.ljust(L,b'\0')[:L]) variants.add(md5(kb).digest()); variants.add(sha256(kb).digest()); variants.add(sha1(kb).digest()[:16]) for key in variants: if len(key) not in (16,24,32): continue for mode in ['ECB','CBC']: ivs=[None] if mode=='ECB' else [bytes(16), kb[:16].ljust(16,b'\0'), kb[-16:].rjust(16,b'\0'), md5(kb).digest()] for iv in ivs: try: pt=aes_decrypt(data,key,mode,iv) if score_ascii(pt)>0.7 or b'0x' in pt.lower() or b'flag' in pt.lower(): print("key",kb,"AES",len(key),mode,iv,"score",score_ascii(pt),pt[:200]) except Exception: pass print("s") test_aes_bytes(bb, key_candidates) print("r5") test_aes_bytes(b_r5, key_candidates)
pythonfrom pathlib import Path imgp=Path('/mnt/data/image.png') img=imgp.read_bytes() len(img), img[:20], img[-100:] (83280, b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02h', b'aH\xf4\xd9\x00\x00\x9a\x96\x86\x9e\xaf \x97/!\x9b-BQ\x14\x0c\xcc>\xac\xd1\x10\xa3\xd1\x10\xb6ea4\x1ab4r\x95\x10B\x08!d\xdeH\xa5\xd2H\xa54\xa4Ri\xa8\x9a\xabZ*\x8dL6\x07\xc7q`\x1am\xf4{\x1d\xf4{M\x8c\xac\x81\xbc=\xe0\xffe\x88b\xba\x932\xac\xc9\x00\x00\x00\x00IEND\xaeB`\x82')
pythonimport re, subprocess, os, textwrap, json, sys, math, statistics strings=re.findall(rb'[ -~]{5,}', img) len(strings), strings[:20], strings[-20:] (411, [b'IDATx^', b'._JC~', b'oo_dff"', b' H3Fju', b'DW)5/', b'Cj 0(', b',)nXb', b'`.(#(', b'4bbbbbb', b'\\*DQ?H(', b'5BQa!rr', b'oW;wwq`', b'OLLLL\\v', b'fgvc10', b"DZN`i'M", b"'&&&&", b'=._JC', b'?111q', b'(3UJHI', b'5\\r|I5'], [b'M+####', b'fdgg!((', b'\\^>uv', b'Ndggi>', b'`s66[c', b'>_}sss', b"]'Cl222", b'_ll,<<<p', b'^u;w.', b'//oCl222', b'sOamm', b'v_TI%', b'6~x&!', b'o@[;v', b'llKr)', b':B>v/Z._B', b':?zzzzzzzz', b'66o\\B:', b'=K6[@', b'{Czzzzzzz'])
pythonimport struct, zlib pos=8 chunks=[] while pos<len(img): length=struct.unpack(">I", img[pos:pos+4])[0]; typ=img[pos+4:pos+8] chunks.append((typ,length,pos)) pos += 8+length+4 chunks[:10], chunks[-5:], len(chunks) ([(b'IHDR', 13, 8), (b'sRGB', 1, 33), (b'gAMA', 4, 46), (b'pHYs', 9, 62), (b'IDAT', 65445, 83), (b'IDAT', 17716, 65540), (b'IEND', 0, 83268)], [(b'gAMA', 4, 46), (b'pHYs', 9, 62), (b'IDAT', 65445, 83), (b'IDAT', 17716, 65540), (b'IEND', 0, 83268)], 7)
pythondef atbash(s): out='' for c in s: if c.islower(): out+=chr(ord('z')-(ord(c)-ord('a'))) elif c.isupper(): out+=chr(ord('Z')-(ord(c)-ord('A'))) elif c.isdigit(): out+=str(9-int(c)) else: out+=c return out for objname,obj in [('s',s),('r5',r5),('letters',letters),('r5letters',''.join(c for c in r5 if c.isalpha()))]: t=atbash(obj) print(objname,t[:200]) if 'flag' in t or '0x' in t: print("match") for r in range(2,10): tt=rail_fence_decrypt(t,r) if any(w in tt for w in ['flag','the','you','void']): print("r",r,tt[:200])
pythonr5letters=''.join(c for c in r5 if c.isalpha()) matches=[] for name,t in transforms_basic(r5letters): low=t.lower() if 'flag' in low or 'flg' in low or 'iflg' in low or 'the' in low or 'you' in low: matches.append((name,t)) for name,t in matches[:100]: print(name,t) print("count",len(matches))
pythonr5digits=''.join(c for c in r5 if c.isdigit()) print(len(r5digits), r5digits[:100]) # ASCII pair/3/rail etc for r in range(2,10): t=rail_fence_decrypt(r5digits,r) if '0x' in t or 'flag' in t: print('raw') # Convert pairs for off in [0,1]: hx=t[off:] if len(hx)%2: hx=hx[:-1] bs=bytes(int(hx[i:i+2]) for i in range(0,len(hx),2) if int(hx[i:i+2])<256) if score_ascii(bs)>0.7 or b'flag' in bs.lower(): print("r",r,"off",off,score_ascii(bs),bs[:100]) print(bs.decode('latin1')[:100]) # try decimal segmentation DP to printable?
pythondef ascii_decimal_decodings(digits, max_solutions=10): # dp score and reconstruct best printables from parsing 2 or 3 digits as 32-126 n=len(digits) dp=[(-1e9,'') for _ in range(n+1)] dp[0]=(0,'') for i in range(n): if dp[i][0]<-1e8: continue for l in [2,3]: if i+l<=n: v=int(digits[i:i+l]) if 32<=v<=126: # score common ch=chr(v) score=1 + (3 if ch.lower() in 'etaoinshrdlu' else 0) + (5 if ch in '{}_' else 0) if dp[i][0]+score>dp[i+l][0]: dp[i+l]=(dp[i][0]+score, dp[i][1]+ch) return dp[n] for name,dig in [('s',digits),('r5',r5digits)]: score,dec=ascii_decimal_decodings(dig) print(name,score,dec[:200],len(dec)) # Also allow 1 for digits as ascii? no
pythonfor name,dig in [('s',digits),('r5',r5digits)]: n=int(dig) bsint=n.to_bytes((n.bit_length()+7)//8,'big') print(name,len(bsint),score_ascii(bsint),bsint[:100],bsint.hex()[:100]) # xor single? best=[] for k in range(256): x=bytes(c^k for c in bsint) if score_ascii(x)>0.7 or b'flag' in x.lower(): best.append((score_ascii(x),k,x[:100])) print(sorted(best, reverse=True)[:3])
pythondef shift_letters_by_prev_digit(s, direction=-1): out=[] cur=0 for ch in s: if ch.isdigit(): cur=int(ch) elif ch.isalpha(): out.append(chr((ord(ch)-97 + direction*cur)%26+97)) return ''.join(out) for name,dat in [('s',s),('r5',r5)]: for direction in [-1,1]: out=shift_letters_by_prev_digit(dat,direction) print(name,direction,out) if any(w in out for w in ['flag','the','you','real','void']): print("match") for r in [2,3,4,5,7]: t=rail_fence_decrypt(out,r) if any(w in t for w in ['flag','the','you','real','void']): print(" rail",r,t[:100])
pythondef shift_letters_by_next_digit(s, direction=-1): out=[] for i,ch in enumerate(s): if ch.isalpha(): # find next digit d=0 for j in range(i+1,len(s)): if s[j].isdigit(): d=int(s[j]); break out.append(chr((ord(ch)-97 + direction*d)%26+97)) return ''.join(out) for name,dat in [('s',s),('r5',r5)]: for direction in [-1,1]: out=shift_letters_by_next_digit(dat,direction) print(name,direction,out) if any(w in out for w in ['flag','the','you','real','void']): print("match")
pythonfor name,dat in [('s',s),('r5',r5)]: bits_ld=''.join('1' if c.isalpha() else '0' for c in dat) print(name,len(bits_ld),bits_ld[:100]) for start in range(5): vals=[int(bits_ld[i:i+5],2) for i in range(start,len(bits_ld)-4,5)] for offset in [0,1]: txt=''.join(chr(v+ord('a')-offset) if offset<=v<=25+offset else '?' for v in vals) if any(w in txt for w in ['flag','the','you','void','real']) or True: print(start,offset,txt) print()
pythonfor name,dat in [('s',s),('r5',r5)]: runs=re.findall(r'\d+|[a-z]+', dat) # For each digit run, convert parity bits to ascii or morse bitstr=''.join(str(int(d)%2) for d in re.findall(r'\d', dat)) print(name, "parity len",len(bitstr), bitstr[:100]) for width in [5,7,8]: for start in range(width): vals=[int(bitstr[i:i+width],2) for i in range(start,len(bitstr)-width+1,width)] if width==5: txt=''.join(chr(v+97) if v<26 else '?' for v in vals) else: txt=''.join(chr(v) if 32<=v<127 else '?' for v in vals) if any(w in txt.lower() for w in ['flag','the','you','void']): print("width
pythonfor name,dat in [('s',s),('r5',r5),('digits',digits),('r5digits',r5digits)]: for rule_name, bits_digit in [ ('parity',''.join(str(int(c)%2) for c in dat if c.isdigit())), ('ge5',''.join('1' if int(c)>=5 else '0' for c in dat if c.isdigit())), ('prime',''.join('1' if c in '2357' else '0' for c in dat if c.isdigit())), ]: bitstr=bits_digit for width in [7,8]: for start in range(width): vals=[int(bitstr[i:i+width],2) for i in range(start,len(bitstr)-width+1,width)] bs2=bytes(vals) if score_ascii(bs2)>0.7 or b'flag' in bs2.lower() or b'0x' in bs2: print(name,rule_name,width,start,score_ascii(bs2),bs2,bs2.decode('latin1'))
pythonfor name,dat in [('s',s),('r5',r5),('r5enc',rail_fence_encrypt(s,5))]: bits01=''.join(c for c in dat if c in '01') print(name,len(bits01),bits01) # Treat 0 dot 1 dash, split by letters/digits others maybe # Extract runs of 0/1 separated by non-01 toks=re.findall(r'[01]+', dat) for mapping in [(('0','.'),('1','-')), (('0','-'),('1','.'))]: tr={a:b for a,b in mapping} mor=' '.join(''.join(tr[ch] for ch in tok) for tok in toks) dec=morse_decode(mor) print(mapping,dec) # group bits ascii for rev in [False,True]: bs=bytes(int((bits01[i:i+8][::-1] if rev else bits01[i:i+8]),2) for i in range(0,len(bits01)-7,8)) print("ascii",rev,bs,bs.decode('latin1'))
pythondef xor_each_line_last(s,width, include_key=False): out=b'' for i in range(0,len(s),width): line=s[i:i+width] if not line: continue key=ord(line[-1]) part=line if include_key else line[:-1] out += bytes(ord(c)^key for c in part) return out for dataname,dat in [('s',s),('r5',r5),('r5enc',rail_fence_encrypt(s,5))]: print("----",dataname) for w in range(2,65): if len(dat)%w==0: for include in [False,True]: out=xor_each_line_last(dat,w,include) if b'0x' in out.lower() or b'flag' in out.lower() or score_ascii(out)>0.8: print("w",w,"inc",include,"score",score_ascii(out),out[:120]) if b'0x' in out.lower() or b'flag'
pythonfor dataname,dat in [('s',s.encode()),('r5',r5.encode()),('bb',bb),('b_r5',b_r5)]: for key in [b')',b'}',b'.',b'=',b'?',b'\x8d',b'\x88']: x=bytes(c^key[0] for c in dat) if score_ascii(x)>0.8 or b'flag' in x.lower() or b'0x' in x.lower(): print(dataname,key,score_ascii(x),x[:100]) if b'flag' in x.lower() or b'0x' in x.lower(): print("match",x)
pythonx=bytes(c^0x88 for c in bb) for pat in [b'0x',b'flag',b'V01',b'v01']: print(pat, x.find(pat)) print(x)
pythonfor objname,obj in [('text',text),('visible',visible),('rawlatin',raw.decode('latin1'))]: n=len(obj) print(objname,n,math.gcd(677,n)) if math.gcd(677,n)==1: for start in range(min(100,n)): out=cyclic_step(obj,677,start) # remove zero-width and nonascii outclean=''.join(ch for ch in out if ch not in '\u200b\u200c\u200d' and 32<=ord(ch)<127) if '0xV01D' in outclean or 'flag' in outclean.lower() or 'the' in outclean.lower()[:100]: print("start",start,outclean[:200]) break print(cyclic_step(obj,677,0)[:200])
pythonseq_vis=cyclic_step(visible,677,0) seq_vis_clean=''.join(ch for ch in seq_vis if ch!='\n') print("contains", seq_vis.find('0xV01D'), seq_vis.lower().find('flag'), seq_vis.find('{'), seq_vis.find('}')) # print around braces for i,ch in enumerate(seq_vis): if ch in '{}': print(i, seq_vis[max(0,i-100):i+100]) # maybe reverse step? seq_vis_rev=cyclic_step(visible,-677,0) for seqname,seq in [('fwd',seq_vis),('rev',seq_vis_rev)]: print(seqname, "0x", seq.find('0x'), 'V01', seq.find('V01'), 'flag', seq.lower().find('flag'), 'brace', seq.find('{'), seq.find('}')) # all substrings with braces for m in re.finditer(r'\{[^}]{0,100}\}', seq): print("brace match",m.group())
pythonfor seqname, seq in [('vis_fwd',seq_vis),('vis_rev',seq_vis_rev),('text_fwd',cyclic_step(text,677,0)),('text_rev',cyclic_step(text,-677,0))]: clean=''.join(ch for ch in seq if ch.isalnum() or ch in '{}_') print(seqname,len(clean), clean[:500]) print("finds", clean.find('0xV01D'), clean.lower().find('flag'), clean.find('{'), clean.find('}')) for m in re.finditer(r'\{[^}]{0,100}\}', clean): print(m.group())
pythondef cyclic_step_bytes(data, step, start=0): n=len(data); out=bytearray(); i=start for _ in range(n): out.append(data[i]); i=(i+step)%n return bytes(out) for step in [677,-677,pow(677,-1,len(raw))]: out=cyclic_step_bytes(raw,step,0) for enc in ['latin1','utf-8']: try: txt=out.decode(enc) except: txt=out.decode(enc,'ignore') clean=''.join(ch for ch in txt if ch.isalnum() or ch in '{}_') print("step",step,"enc",enc,"len",len(clean),"0x",clean.find('0xV01D'),"flag",clean.lower().find('flag'),"brace",clean.find('{'),clean.find('}'),clean[:200]) if '0xV01D' in clean: print(clean[clean.find('0xV01D')-20:clean.find('0xV01D')+100])
pythonfrom pathlib import Path p=Path('/mnt/data/challenge.txt') text=p.read_text('utf-8') len(text), text[:500], text[-500:] (2779, "In the beginning, there was nothing.\nThen nothing whispered: let there be layers upon layers.\nSome say the answer lies within the silence between words.\nOthers believe it hides in plain sight, staring back at you.\nThe number 677 means everything. Or maybe nothing. Who knows?\nDecoded message: dGhpcyBpcyBub3QgdGhlIHdheSBsb2wgdHJ5IGhhcmRlcg==\nSeek and you shall find. Or maybe you won't. HAHAHAHA.\nThe wise man once said: U NEED TO DO 677.\u200b\u200b\u200c\u200c\u200b\u200b\u200c\u200c\u200d\u200b\u200b\u200c\u200c\u200b\u200c\u200b\u200c\u200d\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200c\u200d\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200b\u200d\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200c\u200d\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200b\u200d\u200b\u200b\u200c\u200c\u200b\u200b\u200c\u200b", "ao)\n# NOTE: RAILFENCE RAILS = 5 (source: totally reliable)\n# NOTE: MORSE is standard ITU encoding (wink wink)\n# NOTE: Base64 is used somewhere here (maybe)\nPerhaps the flag is here: 0xV01D{y0u_th0ught_lmao_try_harder_xd}\nOr maybe here: 0xV01D{s0_cl0se_yet_s0_far_hahaha_nope}\nOr here: 0xV01D{alm0st_but_n0t_qu1te_lol}\nOr perhaps it was never here at all.\nThe void speaks in whispers you cannot hear with your ears.\nListen with your tools. All of them. Every. Single. One.\nGood luck. You'll need it. 😈")
pythonfrom pathlib import Path text=Path('/mnt/data/challenge.txt').read_text('utf-8') zw_chars = ['\u200b','\u200c','\u200d','\ufeff','\u2060'] hidden=''.join(c for c in text if c in zw_chars) from collections import Counter Counter(hidden), len(hidden) (Counter({'\u200b': 808, '\u200c': 728, '\u200d': 192}), 1728)
pythonZWSP,ZWNJ,ZWJ='\u200b','\u200c','\u200d' groups=hidden.split(ZWJ) lens=Counter(map(len,groups)) lens, groups[-3:], len(groups) (Counter({8: 192, 0: 1}), ['\u200b\u200b\u200c\u200c\u200b\u200b\u200b\u200b', '\u200b\u200c\u200c\u200b\u200c\u200c\u200c\u200c', ''], 193)
pythonpayload=''.join(chr(int(''.join('0' if c==ZWSP else '1' for c in g),2)) for g in groups if g) payload, len(payload) ('35101021a8r432431nisli89itp1304654316e1t4785939f5xr2l87h8887n1nii25630wrfujy8rlir05m57242l14l9918740y9rc9920v9e35ws39066l107907e0027493ok1g06k69y0ma7rjw8s3n82d618957r3kgit871931mfv2h7wp6m1f10o', 192)
pythonfrom collections import Counter Counter(payload), ''.join(sorted(set(payload))), sum(c.isdigit() for c in payload), sum(c.isalpha() for c in payload) (Counter({'1': 17, '0': 15, '9': 15, '3': 13, '8': 13, '7': 12, '2': 10, '5': 9, '4': 9, '6': 9, 'r': 8, 'i': 7, 'l': 6, 'n': 4, 'f': 4, 'w': 4, 'm': 4, 's': 3, 't': 3, 'e': 3, 'y': 3, 'k': 3, 'a': 2, 'p': 2, 'h': 2, 'j': 2, 'v': 2, 'o': 2, 'g': 2, 'x': 1, 'u': 1, 'c': 1, 'd': 1}), '0123456789acdefghijklmnoprstuvwxy', 122, 70)
pythonlines=text.splitlines() [(i+1,repr(line[-10:]),repr(line[-1]) if line else '') for i,line in enumerate(lines)] [(1, "'s nothing.'", "'.'"), (2, "'on layers.'", "'.'"), (3, "'een words.'", "'.'"), (4, "'ck at you.'", "'.'"), (5, "'Who knows?'", "'?'"), (6, "'hhcmRlcg=='", "'='"), (7, "' HAHAHAHA.'", "'.'"), (8, "'\\u200d\\u200b\\u200c\\u200c\\u200b\\u200c\\u200c\\u200c\\u200c\\u200d'", "'\\u200d'"), (9, "'st me bro)'", "')'"), (10, "' CBC lmao)'", "')'"), (11, "' reliable)'", "')'"), (12, "'wink wink)'", "')'"), (13, "'re (maybe)'", "')'"), (14, "'harder_xd}'", "'}'"), (15, "'haha_nope}'", "'}'"), (16, "'qu1te_lol}'", "'}'"), (17, "'re at all.'", "'.'"), (18, "'your ears.'", "'.'"), (19, "'ngle. One.'", "'.'"), (20, "'need it. 😈'", "'😈'")]
pythondef caesar_letters(s,k): out='' for c in s: if 'a'<=c<='z': out+=chr((ord(c)-97+k)%26+97) else: out+=c return out for k in range(26): t=caesar_letters(s,k) # try b64 decode try: b=base64.b64decode(t+"="*((4-len(t)%4)%4), validate=True) score=sum(32<=x<127 or x in (9,10,13) for x in b)/len(b) if score>.6: print("k",k,score,b[:100]) except: pass if '0xv01d' in t or 'flag' in t: print(k,t) print("rot+1", caesar_letters(s,1)[:200]) print("rot-1", caesar_letters(s,-1)[:200])
pythonimport base64, binascii, hashlib, itertools, re, string, math ct=base64.b64decode(s) len(ct), ct.hex() (144, 'df9d74d74db56bcaf8df6e37d678ac962f3d8ada75df4e3ae78df5e9ed6de3bf39f77f5fe71af697cee1f3cf3b9f59e28b6e7adf4c2b7ee8f2f2b962af4e66e7bdb8da5d7897df75f3be34cbdadcf7ddb4bfd7b7e70b37f74eba975d3bf74eded34dbbe3dde8935834ea4ebdcb499aeeb8f0f2cde7f3677ad7cf79eebde4822b7cef5f77d667efda1ef0a7a9b57f5d28')
pythonlast=''.join(line[-1] for line in lines if line) repr(last), len(last), [hex(ord(c)) for c in last] ("'....?=.\\u200d)))))}}}...😈'", 20, ['0x2e', '0x2e', '0x2e', '0x2e', '0x3f', '0x3d', '0x2e', '0x200d', '0x29', '0x29', '0x29', '0x29', '0x29', '0x7d', '0x7d', '0x7d', '0x2e', '0x2e', '0x2e', '0x1f608'])
pythonn=int(s,36) b=n.to_bytes((n.bit_length()+7)//8,'big') len(b), b[:100], b[-100:], sum(32<=x<127 for x in b)/len(b), b.find(b'0xV') (124, b'"rK\xa7\xc7I\xd6\xbd\xe0\x8b\x9a)No\xefT`\xa9\xc2\x967`;<\xc5\x8a\x03\xda\x1eX\x8e\xbdH\x91\x0f\xc7\xa2\xae*#\xff;j\xdf\xa5I\xae\xe9\xca\xeaQ\xfcDGj\xae\x14Y\x0b\x95\xff\x053J\x1b~<"\xad\x7f\xffz\x91\x0bw\x0c\x05\x83\xd0\xe1\xe6w\x91Z4\x11.1\xbc\xa5\xc7iG\xd2~=\x9e\xa6\xc5\xbc', b'\xc5\x8a\x03\xda\x1eX\x8e\xbdH\x91\x0f\xc7\xa2\xae*#\xff;j\xdf\xa5I\xae\xe9\xca\xeaQ\xfcDGj\xae\x14Y\x0b\x95\xff\x053J\x1b~<"\xad\x7f\xffz\x91\x0bw\x0c\x05\x83\xd0\xe1\xe6w\x91Z4\x11.1\xbc\xa5\xc7iG\xd2~=\x9e\xa6\xc5\xbc p\xa3\xc5\xdc\xcc\xb5\xae\x07\x9c$~2\xccP\x1d\xc2\xe2\xdfZ\x1bI\x0b\xe8', 0.3951612903225806, -1)
pythonbits=''.join('0' if c==ZWSP else '1' if c==ZWNJ else '' for c in hidden) len(bits) 1536
pythonfor off in range(8): bs=bits[off:] out=bytes(int(bs[i:i+8],2) for i in range(0,len(bs)//8*8,8)) score=sum(32<=x<127 or x in (9,10,13) for x in out)/len(out) print(off, score, out[:80])
pythonCounter(c for c in text if c.isspace()), [hex(ord(c)) for c in sorted(set(c for c in text if c.isspace()))] (Counter({' ': 147, '\n': 19}), ['0xa', '0x20'])
pythonfrom pathlib import Path img=Path('/mnt/data/image.png').read_bytes() len(img), img[:8], img.find(b'0xV'), img.find(b'tEXt'), img.find(b'iTXt'), img.find(b'zTXt') (83280, b'\x89PNG\r\n\x1a\n', -1, -1, -1, -1)
pythonimport struct, zlib, binascii data=img pos=8 chunks=[] while pos < len(data): l=struct.unpack(">I",data[pos:pos+4])[0]; typ=data[pos+4:pos+8].decode('latin1') chunks.append((typ,l,pos)) pos+=8+l+4 chunks[:10], chunks[-5:], pos, len(data) ([('IHDR', 13, 8), ('sRGB', 1, 33), ('gAMA', 4, 46), ('pHYs', 9, 62), ('IDAT', 65445, 83), ('IDAT', 17716, 65540), ('IEND', 0, 83268)], [('gAMA', 4, 46), ('pHYs', 9, 62), ('IDAT', 65445, 83), ('IDAT', 17716, 65540), ('IEND', 0, 83268)], 83280, 83280)
pythonascii_last=''.join(line[-1] for line in lines if line and ord(line[-1])<128) repr(ascii_last), len(ascii_last) ("'....?=.)))))}}}...'", 18)
pythonfor i,line in enumerate(lines,1): # Remove zero width? clean=''.join(c for c in line if c not in [ZWSP,ZWNJ,ZWJ]) print(i, repr(clean[-1] if clean else ''), clean[:80])
pythonclean_last=''.join((''.join(c for c in line if c not in [ZWSP,ZWNJ,ZWJ])[-1] if ''.join(c for c in line if c not in [ZWSP,ZWNJ,ZWJ]) else '') for line in lines) repr(clean_last), len(clean_last), clean_last.encode('utf-8'), len(clean_last.encode('utf-8')) ("'....?=..)))))}}}...😈'", 20, b'....?=..)))))}}}...\xf0\x9f\x98\x88', 23)
pythontry: from Crypto.Cipher import AES print("Crypto ok") except Exception as e: print("no",e)
pythontry: from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes print("cryptography ok") except Exception as e: print("no",e)
pythonfrom cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend def aes_decrypt(key, mode, iv=None, data=ct): try: cipher=Cipher(algorithms.AES(key), modes.ECB() if mode=='ECB' else modes.CBC(iv), backend=default_backend()) return cipher.decryptor().update(data)+cipher.decryptor().finalize() except Exception as e: return None def score_bytes(b): if not b: return 0 return sum((32<=x<127) or x in (9,10,13) for x in b)/len(b) def pkcs7_unpad(b): if not b: return b pad=b[-1] if 1<=pad<=16 and b.endswith(bytes([pad])*pad): return b[:-pad] return b candidates=set() # line last variants variants=[] variants.append(last) variants.append(clean_last) variants.append(ascii_last) for v in list(variants): candidates.add(v.encode('utf-8')) candidates.add(v.encode('latin1','ignore')) for i in range(max(0,len(v)-15)): candidates.add(v[i:i+16].encode('utf-8')) be=v.encode('utf-8') for i in range(max(0,len(be)-15)): candidates.add(be[i:i+16]) # common keys common=['677','U NEED TO DO 677','U NEED TO DO 677.','u need to do 677','HAHAHAHA','HAHAHAHA.','hahahaha','void','0xV01D','0xV01D Team','What You See Is Not What You Get','this is not the way lol try harder','dGhpcyBpcyBub3QgdGhlIHdheSBsb2wgdHJ5IGhhcmRlcg==','last character of each line','trust me bro','CBC lmao','ECB','CBC','not CBC','The wise man once said: U NEED TO DO 677.'] for w in common: wb=w.encode() candidates.add(wb) candidates.add(wb[:16].ljust(16,b'\0')) candidates.add(wb[:16].ljust(16,b' ')) # repeat candidates.add((wb*((32//len(wb))+1))[:16]) candidates.add((wb*((48//len(wb))+1))[:24]) candidates.add((wb*((64//len(wb))+1))[:32]) for h in [hashlib.md5(wb).digest(),hashlib.sha1(wb).digest()[:16],hashlib.sha256(wb).digest()[:16],hashlib.sha256(wb).digest(),hashlib.sha512(wb).digest()[:32]]: candidates.add(h) # line chars maybe only not notes, etc. for start in range(len(lines)): for end in range(start+1,len(lines)+1): cl=''.join((''.join(c for c in line if c not in [ZWSP,ZWNJ,ZWJ])[-1] if ''.join(c for c in line if c not in [ZWSP,ZWNJ,ZWJ]) else '') for line in lines[start:end]) eb=cl.encode('utf-8') if len(eb) in [16,24,32]: candidates.add(eb) # ascii only ab=cl.encode('latin1','ignore') if len(ab) in [16,24,32]: candidates.add(ab) # filter keys=[k for k in candidates if len(k) in (16,24,32)] len(keys) 204
pythonfor mode in ['ECB','CBC']: hits=[] for key in keys: ivs=[bytes(16)] # if CBC, include first 16 bytes as iv and decrypt rest? for iv in ivs: data=ct if mode=='CBC': pt=aes_decrypt(key,mode,iv,data) else: pt=aes_decrypt(key,mode,data=data) if pt: u=pkcs7_unpad(pt) sc=score_bytes(u) if b'0xV01D' in u or sc>0.7: hits.append((sc,mode,key,u[:200])) print(mode,len(hits)) for hit in sorted(hits, reverse=True)[:20]: print(hit[0],hit[1],hit[2],hit[3])
pythondef rail_decrypt(cipher, rails): if rails<=1: return cipher # zigzag positions pattern=list(range(rails))+list(range(rails-2,0,-1)) idx=[pattern[i%len(pattern)] for i in range(len(cipher))] counts=[idx.count(r) for r in range(rails)] rails_buf=[];p=0 for c in counts: rails_buf.append(list(cipher[p:p+c]));p+=c pos=[0]*rails;out=[] for r in idx: out.append(rails_buf[r][pos[r]]);pos[r]+=1 return ''.join(out) def rail_encrypt(plain, rails): if rails<=1: return plain rows=['']*rails r=0; d=1 for ch in plain: rows[r]+=ch if r==0: d=1 elif r==rails-1: d=-1 r+=d return ''.join(rows (0, [])
pythonCounter(ct).most_common(20), min(ct), max(ct), len(set(ct)) ([(223, 5), (78, 5), (231, 5), (218, 4), (247, 4), (215, 3), (151, 3), (243, 3), (242, 3), (189, 3), (93, 3), (77, 2), (181, 2), (110, 2), (55, 2), (214, 2), (120, 2), (117, 2), (227, 2), (191, 2)], 11, 248, 90)
pythonfrom math import log2 cnt=Counter(ct) ent=-sum(v/len(ct)*log2(v/len(ct)) for v in cnt.values()) ent 6.285492734523623
pythonletters=''.join(c for c in s if c.isalpha()) digits=''.join(c for c in s if c.isdigit()) letters, len(letters), digits, len(digits) ('arnisliitpetfxrlhnniiwrfujyrlirmllyrcvewsleokgkymarjwsndrkgitmfvhwpmfo', 70, '35101021843243189130465431614785939528788871256308055724214991874099920935390661079070027493106690783826189573871931276110', 122)
pythonimport random, re def unshuffle_from_shuffled(shuffled, seed, method='py'): n=len(shuffled) idx=list(range(n)) random.seed(seed) random.shuffle(idx) # shuffled = [orig[i] for i in idx], so orig[i]=shuffled[j] where idx[j]=i orig=['']*n for j,i in enumerate(idx): orig[i]=shuffled[j] return ''.join(orig) for seed in [677,676,678,8203,8204,8205]: t=unshuffle_from_shuffled(s,seed) if '0x' in t or 'flag' in t.lower() or '0xv' in t.lower(): print(seed,t) print(seed,t[:100], score_bytes(t.encode()))
pythonfor seed in range(10000): t=unshuffle_from_shuffled(s,seed) low=t.lower() if '0xv01d' in low or '0xv' in low or 'flag' in low or 'void' in low: print("seed",seed,t[:200]) break else: print("none")
pythonfor key in [b'o', b'677', b'HAHAHAHA', ascii_last.encode(), clean_last.encode('utf-8'), last.encode('utf-8')]: for data,name in [(s.encode(),'s'),(ct,'ct')]: b=bytes(data[i]^key[i%len(key)] for i in range(len(data))) sc=score_bytes(b) if sc>.5: print(name,key,sc,b[:100])
pythonb=bytes(s.encode()[i]^b'HAHAHAHA'[i%8] for i in range(len(s))) print(b.decode('latin1')) print(Counter(chr(x) for x in b).most_common())
pythonfor key in [b'H',b'A',b'HAHAHAHA',b'677',b'o', ascii_last.encode(), clean_last.encode('utf-8')[:16]]: b=bytes(ct[i]^key[i%len(key)] for i in range(len(ct))) print(key, score_bytes(b), b[:80])
pythondigits=''.join(c for c in s if c.isdigit()) # backtracking parse digits to printable ASCII 32-126 or maybe 0-255 solutions=[] def backtrack(pos, out): if len(solutions)>20: return if pos==len(digits): o=''.join(map(chr,out)) if '0xV' in o or 'flag' in o.lower() or len(o)>0: solutions.append(o) return for l in [2,3]: if pos+l<=len(digits): val=int(digits[pos:pos+l]) if 32<=val<=126: backtrack(pos+l,out+[val]) backtrack(0,[]) len(solutions) 0
python# all ways parse digits into 1-2 <=26 sol=[] def bt(pos, out): if len(out)>100: return if pos==len(digits): sol.append(''.join(chr(96+x) for x in out)) return for l in [1,2]: if pos+l<=len(digits): v=int(digits[pos:pos+l]) if 1<=v<=26: bt(pos+l,out+[v]) bt(0,[]) len(sol) 0
pythonfor n in [2,3,4,5,6,8,12,16,24,32,48,64]: print("chunks",n) print(' '.join(s[i:i+n] for i in range(0,len(s),n))[:500])
pythonfor op in ['xor','add','sub']: if op=='xor': b=bytes(x^(677%256) for x in ct) elif op=='add': b=bytes((x+677)%256 for x in ct) else: b=bytes((x-677)%256 for x in ct) print(op,score_bytes(b),b[:100], b.find(b'0xV'))
pythonalphs=[ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", ] for alph in alphs: for k in [677%64]+list(range(64)): trans=str.maketrans(alph, alph[k:]+alph[:k]) t=s.translate(trans) b=try_base64(t.replace('-','+').replace('_','/')) if b: sc=score_bytes(b) if sc>.65 or b'0xV' in b or b'flag' in b.lower(): print("hit", alph
python# Try base encodings using libs? base64 has b32/b85/a85 for enc,func in [('b32',base64.b32decode),('b85',base64.b85decode),('a85',base64.a85decode)]: try: b=func(s.upper() if enc=='b32' else s) print(enc,len(b),score_bytes(b),b[:100],b.find(b'0xV')) except Exception as e: print(enc,"err",e) # base58 decode implement with BTC alphabet def base_decode(s, alphabet): n=0 for ch in s: if ch not in alphabet: raise ValueError(ch) n=n*len(alphabet)+alphabet.index(ch) return n.to_bytes((n.bit_length()+7)//8,'big') alph58="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" alph62="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" for alph,name in [(alph58,'b58'),(alph62,'b62'),('0123456789abcdefghijklmnopqrstuvwxyz','b36')]: try: b=base_decode(s,alph) print(name,len(b),score_bytes(b),b[:100],b.find(b'0xV')) except Exception as e: print(name,e)
pythonfake_flags=re.findall(r'0xV01D\{[^}]+\}', text) fake_flags ['0xV01D{y0u_th0ught_lmao_try_harder_xd}', '0xV01D{s0_cl0se_yet_s0_far_hahaha_nope}', '0xV01D{alm0st_but_n0t_qu1te_lol}']
pythonfake_flags=re.findall(r'0xV01D\{[^}]+\}', text) fake_flags ['0xV01D{y0u_th0ught_lmao_try_harder_xd}', '0xV01D{s0_cl0se_yet_s0_far_hahaha_nope}', '0xV01D{alm0st_but_n0t_qu1te_lol}'] 1952
pythondef find_aes_hits(data, keys): res=[] # also data first block iv, rest cbc for key in keys: for mode in ['ECB']: pt=aes_decrypt(key, mode, data=data) if pt: u=pkcs7_unpad(pt); sc=score_bytes(u) if b'0xV' in u or b'flag' in u.lower() or sc>.75: res.append((sc,mode,key,u[:200])) for ivname,iv,dd in [('zero',bytes(16),data),('first',data[:16],data[16:] if len(data)>16 else data)]: if len(dd)%16==0: pt=aes_decrypt(key,'CBC',iv,dd) if pt: u=pkcs7_unpad(pt); sc=score_bytes(u) if b'0xV' in u or b'flag' in u.lower() or sc>.75: res.append((sc,'CBC_'+ivname,key,u[:200])) return res # try for raw ct, rail variants base64 decode all_aes_hits=[] for name,t in [('raw',s)] + candidates_strings[:]: b=try_base64(t) if b and len(b)%16==0: hits=find_aes_hits(b,newkeys) for h in hits: all_aes_hits.append((name,)+h) len(all_aes_hits) 11
pythonfor hit in sorted(all_aes_hits, key=lambda x:x[1], reverse=True)[:30]: name,sc,mode,key,u=hit print("----",name,sc,mode,key[:40],len(key)) print(u)
pythontrits=''.join(str({ZWSP:0,ZWNJ:1,ZWJ:2}[c]) for c in hidden) for group in [3,4,5,6,8]: vals=[int(trits[i:i+group],3) for i in range(0,len(trits)//group*group,group)] b=bytes(v for v in vals if v<256) print("group",group,"nvals",len(vals),"bytes",len(b),"score",score_bytes(b), b[:100]) print(b.find(b'0xV'), b.lower().find(b'flag')) # interpret whole base3 int n=int(trits,3) b=n.to_bytes((n.bit_length()+7)//8,'big') print('whole',len(b),score_bytes(b),b[:100],b.find(b'0xV'))
pythonimport itertools chars=[ZWSP,ZWNJ,ZWJ] for perm in itertools.permutations('012'): mp=dict(zip(chars,perm)) tri=''.join(mp[c] for c in hidden) for group in [4,5,6]: vals=[int(tri[i:i+group],3) for i in range(0,len(tri)//group*group,group)] if all(v<256 for v in vals): b=bytes(vals) else: b=bytes(v for v in vals if v<256) sc=score_bytes(b) if sc>0.75 or b"0xV" in b or b"flag" in b.lower(): print("perm",perm,"group",group,"score",sc,"len",len(b), b[:200])
pythonfor mapping in [(str.isdigit,'0 for digit'),(str.isalpha,'0 for alpha')]: pass for digit_bit in ['0','1']: bits2=''.join(digit_bit if c.isdigit() else ('1' if digit_bit=='0' else '0') for c in s) for group in [5,6,7,8]: out=[] for i in range(0,len(bits2)//group*group,group): v=int(bits2[i:i+group],2) if group==5: # Bacon 0-25 out.append(chr(97+v) if v<26 else '?') else: out.append(chr(v)) res=''.join(out) print("digit_bit",digit_bit,"group",group,"score",sum(ch in string.printable for ch in res)/len(res),repr(res[:100])) if 'flag' in res.lower() or '0x' in res.lower(): print('HIT',res)
pythonfor source,t in [('s',s),('r5d',rail_decrypt(s,5)),('r5e',rail_encrypt(s,5))]: for db in ['0','1']: bits2=''.join(db if c.isdigit() else ('1' if db=='0' else '0') for c in t) res=''.join(chr(97+int(bits2[i:i+5],2)) if int(bits2[i:i+5],2)<26 else '?' for i in range(0,len(bits2)//5*5,5)) print(source,db,res)
pythondef decode_groups(groups, z0=ZWSP,z1=ZWNJ, reverse_bits=False, reverse_groups=False): gs=[g for g in groups if g] if reverse_groups: gs=gs[::-1] out=[] for g in gs: bits=''.join('0' if c==z0 else '1' for c in g) if reverse_bits: bits=bits[::-1] out.append(chr(int(bits,2))) return ''.join(out) variants=[] for z0,z1 in [(ZWSP,ZWNJ),(ZWNJ,ZWSP)]: for rb in [False,True]: for rg in [False,True]: t=decode_groups(groups,z0,z1,rb,rg) sc=sum(c in string.printable for c in t)/len(t) variants.append((sc,z0==ZWSP,rb,rg,t)) print(sc,z0==ZWSP,rb,rg,repr(t[:100]))
pythonfor transform in [('not', lambda b: bytes((~x)&255 for x in b)), ('minus128',lambda b: bytes((x-128)%256 for x in b)), ('stripmsb',lambda b: bytes(x&0x7f for x in b)), ('swapnib',lambda b: bytes(((x&15)<<4)|(x>>4) for x in b)), ('revbits',lambda b: bytes(int(f'{x:08b}'[::-1],2) for x in b))]: name,fn=transform b=fn(ct) print(name,score_bytes(b),b[:120],b.find(b'0xV')) # try decompress?
pythonstrip=bytes(x&0x7f for x in ct) print(strip.decode('latin1')) for k in range(128): b=bytes(x^k for x in strip) sc=score_bytes(b) if sc>.95 and (b'flag' in b.lower() or b'0x' in b.lower() or True): # print top maybe with english score pass # rank by English frequency def english_score(b): # return score based on letters space common? text=''.join(chr(x).lower() if 32<=x<127 else ' ' for x in b) common=sum(text.count(ch) for ch in ' etaoinshrdlu') bad=sum(1 for x in b if not (32<=x<127 or x in (9,10,13))) return common - bad*5 scores=[] for k in range(128): b=bytes(x^k for x in strip) scores.append((english_score(b),k,score_bytes(b),b[:100])) for item in sorted(scores, reverse=True)[:10]: print(item)
pythonfrom PIL import Image img=Image.open('/mnt/data/image.png') img.mode, img.size ('RGBA', (616, 580))
pythonimport numpy as np, itertools, math, re, string, base64 arr=np.array(img) # try LSB bits channels RGB/A in row-major, group bytes, both bit orders, first N def bytes_from_bits(bits): return bytes(int(''.join(map(str,bits[i:i+8])),2) for i in range(0,len(bits)//8*8,8)) channels={'r':0,'g':1,'b':2,'a':3} hits=[] for chs in ['r','g','b','a','rgb','rgba','bgr','argb']: inds=[channels[c] for c in chs] bits=[] for pix in arr.reshape(-1,4): for i in inds: bits.append(pix[i]&1) for revbit in [False,True]: b=bytes_from_bits([*bits] if not revbit else [*bits]) if revbit: b=bytes(int(''.join(str(x) for x in bits[i:i+8][::-1]),2) for i in range(0,len(bits)//8*8,8)) head=b[:100 0
pythonimport base64, zlib, bz2, lzma, gzip, re, string, math, hashlib, itertools, collections, functools, time, random flag_re=re.compile(rb'0xV01D\{[^}]{1,100}\}', re.I) def is_interesting(b): return flag_re.search(b) or b'0xV' in b or b'flag' in b.lower() or b'v01d' in b.lower() def to_bytes(x): return x.encode() if isinstance(x,str) else x def to_str(b): try: return b.decode('latin1') except: return ''.join(chr(x) for x in b) def rot_alnum(t,k,alphabet="0123456789abcdefghijklmnopqrstuvwxyz"): trans=str.maketrans(alphabet, alphabet[k:]+alphabet[:k]) return t.translate(trans) def atbash_alnum(t,alphabet="0123456789abcdefghijklmnopqrstuvwxyz"): return t.translate(str.maketrans(alphabet, alphabet[::-1])) start
python# Recompute variables cleanly from pathlib import Path text=Path('/mnt/data/challenge.txt').read_text('utf-8') ZWSP,ZWNJ,ZWJ='\u200b','\u200c','\u200d' hidden=''.join(c for c in text if c in (ZWSP,ZWNJ,ZWJ)) groups=hidden.split(ZWJ) s=''.join(chr(int(''.join('0' if c==ZWSP else '1' for c in g),2)) for g in groups if g) bits=''.join('0' if c==ZWSP else '1' if c==ZWNJ else '' for c in hidden) letters_only=''.join(c for c in s if c.isalpha()) digits_only=''.join(c for c in s if c.isdigit()) len(s), s[:50], len(bits), len(letters_only), len(digits_only) (192, '35101021a8r432431nisli89itp1304654316e1t4785939f5x', 1536, 70, 122)
python# retry BFS broader but with seen, limited import base64, zlib, bz2, lzma, gzip, re, string, math, hashlib, itertools, collections, time flag_re=re.compile(rb'0xV01D\{[^}]{1,120}\}', re.I) def is_interesting(b): return flag_re.search(b) or b'0xV01D' in b or b'v01d' in b.lower() or b'flag' in b.lower() def rail_decrypt(cipher, rails): if rails<=1: return cipher pattern=list(range(rails))+list(range(rails-2,0,-1)) idx=[pattern[i%len(pattern)] for i in range(len(cipher))] counts=[idx.count(r) for r in range(rails)] rails_buf=[]; p=0 for c in counts: rails_buf.append(list(cipher[p:p+c])); p+=c pos=[0]*rails; out=[] for r in idx: out.append(rails_buf[r][pos[r]]); pos
python# BFS for exact 0xV/v01d only, ignoring 'flag' def is_hit(b): return flag_re.search(b) or b'0xV01D' in b or b'0xv01d' in b.lower() or b'v01d{' in b.lower() seen=set(); queue=collections.deque((name,b,0) for name,b in start_items) limit=100000 cnt=0; found=[] while queue and cnt<limit: name,b,depth=queue.popleft(); cnt+=1 if is_hit(b): found.append((name,b[:500])); print("FOUND",name,b[:500]); break if depth>=3: continue key=(hashlib.md5(b).digest(), depth) if key in seen: continue seen.add(key) outs=[] if len(b)>0 and len(b)<5000: try: t=b.decode('ascii') if all(ch in string.printable for ch in t): for label,func in [ ('b64',lambda x:base64.b64decode
python# Build transformation found t=rot_alnum(s,14) u=rail_decrypt(t,13) u, len(u), u.find('flag'), u[u.find('flag')-20:u.find('flag')+50] ('howimtgnzymu3w6ffnz8ml7mj53mmxfgeuh7km1eleicljfifhhn1mz9nkml0fgyenn5fhegeiin1znslkrnfhknshfwwtkhffjjw5mjecfft0meealegbi1ewh5jji6g0ntf9jolhe0kgf6gzkzhjcnillgev55nenlemswfmflag5khxhl2aya2kqi5v7n', 192, 170, 'cnillgev55nenlemswfmflag5khxhl2aya2kqi5v7n')
pythonfor k in [677%36, -677%36, 677%26, -677%26]: tt=rot_alnum(s,k) if k in range(36) else caesar_letters(s,k) print(k, tt[:100]) # rail 5 decrypt/encrypt for r in [5,13,14,29]: print('r',r,rail_decrypt(tt,r)[:100]) print()
pythondef rot47(s,k=47): out='' for c in s: o=ord(c) if 33<=o<=126: out+=chr(33+(o-33+k)%94) else: out+=c return out for k in [47,677%94, -677%94]: t=rot47(s,k) print("k",k,t[:200]) if '0x' in t: print(t) b=try_base64(t) if b: print("b64",score_bytes(b),b[:50])
pythonidx=text.find(ZWSP) idx, len(text[:idx]), len(text[:idx].encode()), text[:idx][-50:] (438, 438, 438, 'AHAHAHA.\nThe wise man once said: U NEED TO DO 677.')
pythonlen(text.encode('utf-8')), len(hidden.encode('utf-8')), len(text)-len(hidden), len(text.encode())-len(hidden.encode()) (6238, 5184, 1051, 1054)
python# Decode hidden groups starting from each delimiter/char? # For each start position in hidden run, split by ZWJ then groups of length 8 valid -> payload; look for flags/english def decode_from_sub(h): gr=h.split(ZWJ) outs=[] for g in gr: if len(g)==8 and all(c in (ZWSP,ZWNJ) for c in g): bits=''.join('0' if c==ZWSP else '1' for c in g) outs.append(chr(int(bits,2))) return ''.join(outs) for start in [0,677,676,678,8203%len(hidden), len(hidden)-677]: t=decode_from_sub(hidden[start:]) print("start",start,"len",len(t),"score",sum(c in string.printable for c in t)/max(1,len(t)),repr(t[:200]))
pythonfor N in [677,678,676,1728-677]: t=decode_from_sub(hidden[:N]) print("N",N,"len",len(t),repr(t[:200]), "b64?", try_base64(t)[:10] if try_base64(t) else None)
pythondata=s.encode() cands=[] for kl in range(1,41): key=bytes(best_key_for_col(data[i::kl]) for i in range(kl)) pt=bytes(c^key[i%kl] for i,c in enumerate(data)) sc=score_text(pt)/len(pt) if sc>4 or b'0x' in pt or b'flag' in pt.lower(): cands.append((sc,kl,key,pt)) for sc,kl,key,pt in sorted(cands, reverse=True)[:20]: print('kl',kl,'score',sc,'key',key,'pt',pt[:200])
pythondef columnar_decrypt(cipher,key): n=len(key); L=len(cipher) # order columns by key chars stable order=sorted(range(n), key=lambda i:(key[i],i)) rows=math.ceil(L/n) # column lengths when plaintext row-wise fill full_cols=L % n col_lens=[rows if (full_cols==0 or i<full_cols) else rows-1 for i in range(n)] cols=['']*n; p=0 for i in order: l=col_lens[i]; cols[i]=cipher[p:p+l]; p+=l out=[] for r in range(rows): for c in range(n): if r<len(cols[c]): out.append(cols[c][r]) return ''.join(out) def columnar_encrypt(plain,key): n=len(key); rows=math.ceil(len(plain)/n) cols=['']*n for i,ch in enumerate(plain): cols[i%n]+=ch order=sorted(range(n), key=lambda i:(key[i],i)) return ''.join(cols[i] for i in order) for key in ['677','676','077','U NEED TO DO 677','needtodo
pythonu=rail_decrypt(rot_alnum(s,14),13) # Explore further one/two transforms on u for 0x/flag for k in range(36): v=rot_alnum(u,k) if '0xv' in v.lower() or 'flag' in v.lower() or 'void' in v.lower(): print("rot",k,v[:200]) for r in range(2,50): for label,func in [('rd',rail_decrypt),('re',rail_encrypt)]: v=func(u,r) if '0xv' in v.lower() or 'flag' in v.lower() or 'void' in v.lower(): print(label,r,v[:200]) # b64? b=try_base64(v) if b and (b'0xV' in b or b'flag' in b.lower() or score_bytes(b)>.65): print("b64",label,r,score_bytes(b),b[:100]) # substring around flag maybe shift chars? u 'howimtgnzymu3w6ffnz8ml7mj53mmxfgeuh7km1eleicljfifhhn1mz9nkml0fgyenn5fhegeiin1znslkrnfhknshfwwtkhffjjw5mjecfft0meealegbi1ewh5jji6g0ntf9jolhe0kgf6gzkzhjcnillgev55nenlemswfmflag5khxhl2aya2kqi5v7n'
pythonb=try_base64(u) len(b), score_bytes(b), b[:100], b.hex()[:100] (144, 0.3611111111111111, b'\x86\x8c"\x9a\xd8\'\xcf)\xae\xdf\x0e\x9f~|\xfc\x9a^\xe6\x8f\x9d\xe6\x9b\x17\xe0z\xe8{\x92m^\x95\xe8\x9c\x967\xe2~\x18g\xd6l\xfd\x9eI\xa5\xd1\xf82zy\xf9~\x17\xa0z(\xa7\xd79\xec\x96J\xe7~\x19\'\xb2\x17\xf0\xc2\xd9!}\xf8\xe3\xc3\x99\xa3y\xc7\xdf\xb7I\x9ey\xa9^\x81\xb8\xb5{\x08y\x8e8\xba\x83I\xed\x7f', '868c229ad827cf29aedf0e9f7e7cfc9a5ee68f9de69b17e07ae87b926d5e95e89c9637e27e1867d66cfd9e49a5d1f8327a79')
pythonfor r in [5,13,6,7]: for label,func in [('d',rail_decrypt),('e',rail_encrypt)]: v=func(u,r) print(label,r,v[:200], 'flagpos', v.find('flag'), 'howpos', v.find('how'))
pythonalph="0123456789abcdefghijklmnopqrstuvwxyz" def vig_alnum(t,key,decode=True): out=[]; ki=0 shifts=[] for ch in key: if ch in alph: shifts.append(alph.index(ch)) elif ch.isdigit(): shifts.append(int(ch)) elif ch.isalpha(): shifts.append(ord(ch.lower())-97) if not shifts: return t for ch in t: if ch in alph: sh=shifts[ki%len(shifts)] if decode: sh=-sh out.append(alph[(alph.index(ch)+sh)%len(alph)]) ki+=1 else: out.append(ch) return ''.join(out) for key in ['677','676','HAHAHAHA','void','0xV01D','needtodo677','u']: for dec in [True,False]: v=vig_alnum(s,key,dec) for r in [5,6
pythonwords=['how','flag','the','you','need','void','try','hard','lmao','close','not','what','get','see','real'] matches=[] for k in range(36): t=rot_alnum(s,k) for r in range(2,50): for label,func in [('rd',rail_decrypt),('re',rail_encrypt)]: v=func(t,r) wscore=sum(v.count(w) for w in words) if wscore: matches.append((wscore,k,label,r,v[:200])) for m in sorted(matches, reverse=True)[:50]: print(m[:4],m[4])
pythonu_letters=''.join(c for c in u if c.isalpha()) u_digits=''.join(c for c in u if c.isdigit()) u_letters, len(u_letters), u_digits[:100], len(u_digits) ('howimtgnzymuwffnzmlmjmmxfgeuhkmeleicljfifhhnmznkmlfgyennfhegeiinznslkrnfhknshfwwtkhffjjwmjecfftmeealegbiewhjjigntfjolhekgfgzkzhjcnillgevnenlemswfmflagkhxhlayakqivn', 163, '36875371190515015609065552257', 29)
pythonfor k in range(26): v=caesar_letters(u_letters,k) if any(w in v for w in ['the','you','flag','how','need','void']): print(k,v[:200])
pythonflag_matches=[] for source_name,base in [('s',s),('rev',s[::-1])]: for k in range(36): t=rot_alnum(base,k) for r in range(2,80): for label,func in [('rd',rail_decrypt),('re',rail_encrypt)]: v=func(t,r) pos=v.find('flag') if pos!=-1: flag_matches.append((source_name,k,label,r,pos,v[max(0,pos-30):pos+60],v)) len(flag_matches) 4
pythonfor m in flag_matches: print(m[:6])
pythonv=flag_matches[-1][-1] v, len(v) ('2aya2kqi5v7nfmflag5khxhlev55nenlemswgzkzhjcnillgf9jolhe0kgf6ewh5jji6g0ntt0meealegbi1ffjjw5mjecfffhknshfwwtkheiin1znslkrn0fgyenn5fhegfhhn1mz9nkmlkm1eleicljfij53mmxfgeuh73w6ffnz8ml7mhowimtgnzymu', 192)
pythondef atbash_letters(s): return ''.join(chr(122-(ord(c)-97)) if 'a'<=c<='z' else c for c in s) for v in [u, atbash_letters(u), atbash_alnum(u)]: print(v[:200]) print('flag',v.find('flag'),'0x',v.find('0x'), 'how', v.find('how'), 'the', v.find('the'))
pythondef show_trans_text(t, words=['the','you','flag','how','need']): out=[] for name,v in transpositions(t): score=sum(v.count(w) for w in words) if score: out.append((score,name,v[:200])) return sorted(out, reverse=True)[:20] show_trans_text(u_letters)[:10] [(2, 'r1c163_revrows', 'howimtgnzymuwffnzmlmjmmxfgeuhkmeleicljfifhhnmznkmlfgyennfhegeiinznslkrnfhknshfwwtkhffjjwmjecfftmeealegbiewhjjigntfjolhekgfgzkzhjcnillgevnenlemswfmflagkhxhlayakqivn'), (2, 'r1c163_fillcol_readrow', 'howimtgnzymuwffnzmlmjmmxfgeuhkmeleicljfifhhnmznkmlfgyennfhegeiinznslkrnfhknshfwwtkhffjjwmjecfftmeealegbiewhjjigntfjolhekgfgzkzhjcnillgevnenlemswfmflagkhxhlayakqivn'), (2, 'r1c163_col_revrow', 'howimtgnzymuwffnzmlmjmmxfgeuhkmeleicljfifhhnmznkmlfgyennfhegeiinznslkrnfhknshfwwtkhffjjwmjecfftmeealegbiewhjjigntfjolhekgfgzkzhjcnillgevnenlemswfmflagkhxhlayakqivn'), (2, 'r1c163_col', 'howimtgnzymuwffnzmlmjmmxfgeuhkmeleicljfifhhnmznkmlfgyennfhegeiinznslkrnfhknshfwwtkhffjjwmjecfftmeealegbiewhjjigntfjolhekgfgzkzhjcnillgevnenlemswfmflagkhxhlayakqivn'), (2, 'r163c1_rowrev', 'howimtgnzymuwffnzmlmjmmxfgeuhkmeleicljfifhhnmznkmlfgyennfhegeiinznslkrnfhknshfwwtkhffjjwmjecfftmeealegbiewhjjigntfjolhekgfgzkzhjcnillgevnenlemswfmflagkhxhlayakqivn'), (2, 'r163c1_fillcol_readrow', 'howimtgnzymuwffnzmlmjmmxfgeuhkmeleicljfifhhnmznkmlfgyennfhegeiinznslkrnfhknshfwwtkhffjjwmjecfftmeealegbiewhjjigntfjolhekgfgzkzhjcnillgevnenlemswfmflagkhxhlayakqivn'), (2, 'r163c1_col', 'howimtgnzymuwffnzmlmjmmxfgeuhkmeleicljfifhhnmznkmlfgyennfhegeiinznslkrnfhknshfwwtkhffjjwmjecfftmeealegbiewhjjigntfjolhekgfgzkzhjcnillgevnenlemswfmflagkhxhlayakqivn')]
pythonraw=Path('/mnt/data/challenge.txt').read_bytes() raw_lines=raw.splitlines() last_bytes=bytes(line[-1] for line in raw_lines if line) last_bytes, len(last_bytes), last_bytes[:16] (b'....?=.\x8d)))))}}}...\x88', 20, b'....?=.\x8d)))))}}}')
python# Add last_bytes variants for AES for L in [16,20]: print(L,last_bytes[:L]) cand2=set(newkeys if 'newkeys' in globals() else []) for src in [last_bytes,last_bytes[:16], last_bytes[-16:], last_bytes[1:17], last_bytes[:20]]: for L in [16,24,32]: if len(src)>=L: cand2.add(src[:L]) if len(src)<L: cand2.add(src.ljust(L,b'\0')); cand2.add(src.ljust(L,b' ')) cand2.add(hashlib.md5(src).digest()) cand2.add(hashlib.sha256(src).digest()[:L] if L<32 else hashlib.sha256(src).digest()) keys2=[k for k in cand2 if len(k) in (16,24,32)] hits=find_aes_hits(ct,keys2) len(hits), hits[:5] (0, [])
pythonprefix=b'0xV01D{' for kl in range(1,41): key=[None]*kl ok=True for i,pb in enumerate(prefix): pos=i%kl val=ct[i]^pb if key[pos] is not None and key[pos]!=val: ok=False;break key[pos]=val if not ok: continue # fill unknown by best scoring column key2=bytearray(kl) for j in range(kl): if key[j] is not None: key2[j]=key[j] else: key2[j]=best_key_for_col(ct[j::kl]) pt=bytes(c^key2[i%kl] for i,c in enumerate(ct)) if score_bytes(pt)>0.8 or b'0xV' in pt: print("kl",kl,"score",score_bytes(pt),'key',key2,'pt',pt[:200])
Mình bóc được tầng stego chắc chắn trong challenge.txt, nhưng chưa thể xác nhận flag hợp lệ từ artifact bạn gửi. File có nhiều mồi nhử: Base64 visible decode ra câu “this is not the way lol try harder”, 3 flag nhìn thấy đều được đặt trong ngữ cảnh “maybe / try harder”, và các note cũng có vẻ troll. (challenge.txt)
Kết quả chắc chắn nhất hiện tại là payload ẩn bằng zero-width characters:
text35101021a8r432431nisli89itp1304654316e1t4785939f5xr2l87h8887n1nii25630wrfujy8rlir05m57242l14l9918740y9rc9920v9e35ws39066l107907e0027493ok1g06k69y0ma7rjw8s3n82d618957r3kgit871931mfv2h7wp6m1f10o
Mình không khuyến nghị submit các flag sau vì chúng là decoy:
text0xV01D{y0u_th0ught_lmao_try_harder_xd} 0xV01D{s0_cl0se_yet_s0_far_hahaha_nope} 0xV01D{alm0st_but_n0t_qu1te_lol}
Tên challenge là:
textWhat You See Is Not What You Get
Nội dung file có hint:
textThe answer lies within the silence between words hides in plain sight Listen with your tools
=> Đây là dấu hiệu rất rõ của invisible / zero-width steganography.
Lệnh dùng:
bashfile challenge.txt cat challenge.txt grep -aoE '0xV01D\{[^}]+\}' challenge.txt
Kết quả grep ra các flag nhìn thấy, nhưng đều là mồi nhử.
Decode Base64 nhìn thấy:
bashecho 'dGhpcyBpcyBub3QgdGhlIHdheSBsb2wgdHJ5IGhhcmRlcg==' | base64 -d
Output:
textthis is not the way lol try harder
=> Base64 này cũng là decoy.
Trong file có 3 ký tự ẩn:
textU+200B ZERO WIDTH SPACE U+200C ZERO WIDTH NON-JOINER U+200D ZERO WIDTH JOINER
Thống kê:
textU+200B: 808 U+200C: 728 U+200D: 192 Total : 1728
Pattern rất đẹp: U+200D đóng vai trò separator, mỗi block trước nó dài đúng 8 ký tự. Vì vậy map:
textU+200B -> 0 U+200C -> 1 U+200D -> separator
mỗi block 8 bit thành 1 byte ASCII.
python#!/usr/bin/env python3 from pathlib import Path import sys import base64 from collections import Counter ZWSP = "\u200b" # zero width space ZWNJ = "\u200c" # zero width non-joiner ZWJ = "\u200d" # zero width joiner def rail_fence_decrypt(cipher: str, rails: int) -> str: if rails <= 1: return cipher pattern = list(range(rails)) + list(range(rails - 2, 0, -1)) rail_index = [pattern[i % len(pattern)] for i in range(len(cipher))] counts = [rail_index.count(r) for r in range(rails)] rails_buf = [] p = 0 for c in counts: rails_buf.append(list(cipher[p:p + c])) p += c pos = [0] * rails plain = [] for r in rail_index: plain.append(rails_buf[r][pos[r]]) pos[r] += 1 return "".join(plain) def main(path: str): text = Path(path).read_text(encoding="utf-8") hidden = "".join(c for c in text if c in (ZWSP, ZWNJ, ZWJ)) print("[+] zero-width chars:", len(hidden)) print("[+] counts:") for k, v in Counter(hidden).items(): print(f" U+{ord(k):04X}: {v}") groups = hidden.split(ZWJ) groups = [g for g in groups if g] print("[+] groups:", len(groups)) print("[+] group lengths:", sorted(set(map(len, groups)))) if not all(len(g) == 8 for g in groups): raise ValueError("Không phải tất cả group đều dài 8 bit") out = [] for g in groups: bits = "".join("0" if c == ZWSP else "1" for c in g) out.append(chr(int(bits, 2))) payload = "".join(out) print("\n[+] extracted payload:") print(payload) print("\n[+] try visible-looking Base64 decode of payload:") try: raw = base64.b64decode(payload + "=" * ((4 - len(payload) % 4) % 4)) print(" decoded length:", len(raw)) print(" hex preview:", raw[:64].hex()) except Exception as e: print(" failed:", e) print("\n[+] rail fence thử theo hint rails=5:") print(rail_fence_decrypt(payload, 5)) if __name__ == "__main__": if len(sys.argv) != 2: print(f"Usage: {sys.argv[0]} challenge.txt") sys.exit(1) main(sys.argv[1])
Chạy:
bashpython3 solve.py challenge.txt
Output quan trọng:
text[+] zero-width chars: 1728 [+] groups: 192 [+] group lengths: [8] [+] extracted payload: 35101021a8r432431nisli89itp1304654316e1t4785939f5xr2l87h8887n1nii25630wrfujy8rlir05m57242l14l9918740y9rc9920v9e35ws39066l107907e0027493ok1g06k69y0ma7rjw8s3n82d618957r3kgit871931mfv2h7wp6m1f10o
Mình đã thử các hướng sau trên payload:
textBase64 decode Rail fence rails=5 Rail fence nhiều rails khác XOR với 677 / HAHAHAHA / last-char-of-lines AES ECB/CBC với key suy ra từ các hint Reverse / ROT / Base36 / Base85 Morse mapping từ zero-width chars
Không có output nào ra dạng xác thực:
text0xV01D{...}
Với đúng file bạn gửi, mình xác định được tầng stego chính là zero-width binary, nhưng chưa tìm được flag hợp lệ. Khả năng cao còn thiếu artifact gốc từ nút “Download Challenge” hoặc file này đã được dựng để troll với payload tầng sau chưa đủ thông tin/key.
Payload cần tiếp tục xử lý là:
text35101021a8r432431nisli89itp1304654316e1t4785939f5xr2l87h8887n1nii25630wrfujy8rlir05m57242l14l9918740y9rc9920v9e35ws39066l107907e0027493ok1g06k69y0ma7rjw8s3n82d618957r3kgit871931mfv2h7wp6m1f10o
Gửi thêm file gốc tải từ challenge, mình sẽ nối tiếp từ payload này để ra flag submit được.