-
-
Save benmanns/2ba510748286cfd221bc to your computer and use it in GitHub Desktop.
recover key from CodeIgniter homegrown crypto
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# CodeIgniter pre-2.2 non-mcrypt Encrypt reverser. | |
# Finds the key by partially-known plaintext attack. | |
# Written by Yuki Izumi. Placed in the public domain. | |
import codecs | |
import re | |
import sys | |
import time | |
def decode(s, key): | |
r = bytearray() | |
for i in range(len(s) // 2): | |
r.append(s[i*2] ^ s[i*2+1] ^ key[(i*2)%40] ^ key[(i*2+1)%40]) | |
return bytes(r) | |
def find_key(known, encrypted): | |
key = bytearray(b'0') * 40 | |
confirmed = [False] * 20 | |
hexstr = b'0123456789abcdef' | |
ix = 0 | |
while not all(confirmed): | |
if confirmed[ix%20]: | |
ix += 1 | |
continue | |
kcompb = known[ix::20] | |
for k in range(256): | |
key[(ix*2)%40] = hexstr[k&0xf] | |
key[(ix*2+1)%40] = hexstr[k>>4] | |
r = decode(encrypted, key) | |
kcomp = kcompb | |
rcomp = r[ix::20][:len(kcomp)] | |
while True: | |
try: | |
j = kcomp.index(b' ') | |
except ValueError: | |
break | |
kcomp = kcomp[:j] + kcomp[j+1:] | |
rcomp = rcomp[:j] + rcomp[j+1:] | |
if kcomp[0] == rcomp[0]: | |
confirmed[ix%20] = True | |
break | |
if not confirmed[ix%20]: | |
return None | |
ix += 1 | |
return key | |
with open(sys.argv[1], 'r') as f: | |
encrypted = f.read().split("\n", 2)[0] | |
encrypted = codecs.decode(encrypted.encode('ascii'), 'base64') | |
# Try each of these; space represents an unknown value. Here we account for | |
# the unknown size of the session array in general. We just need one byte of | |
# known plaintext for each index of the key, i.e. as long as there's at least | |
# one value in each 'column'. | |
knowns = ([ | |
b'a: :{s:10:"session_i' + | |
b'd";s:32:" ' | |
, | |
b'a: :{s:10:"session_' + | |
b'id";s:32:" ' | |
, | |
b'a: :{s:10:"session' + | |
b'_id";s:32:" ' | |
]) | |
key = None | |
for known in knowns: | |
key = find_key(known, encrypted) | |
if key: | |
break | |
if not key: | |
print("Could not recover key.") | |
exit(1) | |
print(key.decode('ascii')) | |
print(decode(encrypted, key)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment