#!/usr/bin/env python3
import random, string, sys
chars = string.ascii_lowercase + string.ascii_uppercase + string.digits + string.punctuation
def func1(s, key):
r = ''
for i in range(len(s)):
if s[i] in chars:
if s[i] in string.ascii_lowercase: z = string.ascii_lowercase
elif s[i] in string.ascii_uppercase: z = string.ascii_uppercase
elif s[i] in string.digits: z = string.digits
else: z = string.punctuation
r += z[(z.index(s[i]) + key) % len(z)]
else:
r += s[i]
return r
def func2(s):
return s.translate(s.maketrans(chars, chars[13:] + chars[:13]))
def encrypt(s):
key = random.getrandbits(128)
r = s
for _ in range(8):
r = func1(r, key)
r = func2(r)
return r
def main():
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:
continue
if __name__ == '__main__':
if len(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 string
def rev2(s):
return s.translate(s.maketrans(chars[13:] + chars[:13],chars))
def rev1(s, keys):
r = ''
for i in range(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 r
def dec(s,key):
r = s
for _ in range(8):
r = rev2(r)
r = rev1(r, key)
return r
a = string.ascii_lowercase
b = string.ascii_uppercase
c = string.digits
d = string.punctuation
keypair = []
for key in range(0xffff):
z = [key%len(a),key%len(b),key%len(c),key%len(d)]
if(z in keypair):
break
else:
keypair.append(z)
chars = string.ascii_lowercase + string.ascii_uppercase + string.digits + string.punctuation
f = 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")