#!/usr/bin/env python3import random, string, syschars = string.ascii_lowercase + string.ascii_uppercase + string.digits + string.punctuationdeffunc1(s,key): r =''for i inrange(len(s)):if s[i]in chars:if s[i]in string.ascii_lowercase: z = string.ascii_lowercaseelif s[i]in string.ascii_uppercase: z = string.ascii_uppercaseelif s[i]in string.digits: z = string.digitselse: z = string.punctuation r += z[(z.index(s[i])+ key) %len(z)]else: r += s[i]return rdeffunc2(s):return s.translate(s.maketrans(chars, chars[13:] + chars[:13]))defencrypt(s): key = random.getrandbits(128) r = sfor _ inrange(8): r =func1(r, key) r =func2(r)return rdefmain(): fns = sys.argv[1:]for fn in fns:try: x =open(fn, 'r').read() f =open(fn +'.enc', 'w') f.write(encrypt(x)) f.close()except:continueif__name__=='__main__':iflen(sys.argv)<2:print(f'Usage: {sys.argv[0]} <file>')print(f'Example: {sys.argv[0]} flag.html') sys.exit()main()
Terlihat terdapat 2 fungsi yang dijalankan pada fungsi enkripsi , fungsi pertama melakukan penambahan nilai index pada charset X , fungsi kedua melakukan translate. Karena key cukup besar nilainya yaitu 128 bit , maka bruteforce 128 bit key bukan solusinya. Kalau kita lihat berdasarkan nilai modulus ( panjang charset - 26 26 10 32) maka kita dapat memetakan nilai keynya. Hal yang perlu dilakukan adalah melakukan bruteforce kemungkinan pemetaan key dan berhenti jika nilai pemetaan sudah pernah digenerate sebelumnya ( karena akan berulang nantinya ). Selanjutnya tinggal decrypt saja , ubah + jadi - . Fungsi kedua adalah translasi , semacam membuat dictionary lalu melakukan translate. Jadi tinggal dibalik saja nilai chars dan chars[13:] + chars[:13]. Berikut solver yang kami gunakan
import stringdefrev2(s):return s.translate(s.maketrans(chars[13:] + chars[:13],chars))defrev1(s,keys): r =''for i inrange(len(s)):if s[i]in chars:if s[i]in string.ascii_lowercase: z = string.ascii_lowercase key = keys[0]elif s[i]in string.ascii_uppercase: z = string.ascii_uppercase key = keys[1]elif s[i]in string.digits: z = string.digits key = keys[2]else: z = string.punctuation key = keys[3] r += z[(z.index(s[i])- key) %len(z)]else: r += s[i]return rdefdec(s,key): r = sfor _ inrange(8): r =rev2(r) r =rev1(r, key)return ra = string.ascii_lowercaseb = string.ascii_uppercasec = string.digitsd = string.punctuationkeypair = []for key inrange(0xffff): z = [key%len(a),key%len(b),key%len(c),key%len(d)]if(z in keypair):breakelse: keypair.append(z)chars = string.ascii_lowercase + string.ascii_uppercase + string.digits + string.punctuationf =open("flag.html.enc","r").read()g =open("res","w")for key in keypair: tmp =dec(f,key)if(tmp[:6]=="<html>"): g.write(tmp) g.write("\n")