#!/usr/bin/python2.7
"Decodes AES encrypted config of Kronos (from captured response)"

__AUTHOR__ = 'hasherezade'

import argparse
import hashlib
from Crypto.Cipher import AES

BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) 
unpad = lambda s : s[:-ord(s[len(s)-1:])]

def expand_key(key, dest_len):
    while len(key) < dest_len:
        key = key + key
    return key[:dest_len]

def derive_key(bot_id, key_len):
    buf_hash = hashlib.md5(bot_id).hexdigest()
    return expand_key(buf_hash, key_len)

def aes_cbc_decrypt(enc, key, iv):
    cipher = AES.new(key, AES.MODE_CBC, iv)
    return cipher.decrypt(enc)

def dump_to_file(filename, data):
    with open(filename, 'wb') as f:
        f.write(data)

def main():
    parser = argparse.ArgumentParser(description="Kronos response decoder (a=1)")
    parser.add_argument('--datafile',dest="datafile",default=None,help="File with the response data (connect.php?a=1)", required=True)
    parser.add_argument('--outfile',dest="outfile",default="out.bin", help="Where to dump the output", required=False)
    parser.add_argument('--botid',dest="bot_id", help="The BotId", required=True)
    args = parser.parse_args()

    key = derive_key(args.bot_id, 16)
    print key

    data = open(args.datafile, 'rb').read()
    data_len = len(data)
    iv = data[:16]

    output = aes_cbc_decrypt(data[16:], key, iv)
    print len(output)

    if output is None:
        print "Output is empty"
        return

    if args.outfile is not None:
        dump_to_file(args.outfile, output)
        print "Dumped decoded to: %s" % (args.outfile)
    else:
        print output
        return

if __name__ == '__main__':
    main()
