#!/usr/bin/python2.7
"Decodes dyreza resources from the DLL"

__AUTHOR__ = 'hasherezade'
#using elements from:  http://lokalhost.pl/x/dyre.py by @maciekkotowicz

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 aes_decrypt(enc, iv, key):
    cipher = AES.new(key, AES.MODE_CBC, iv )
    return unpad(cipher.decrypt(enc))
   
###
# author: @maciekkotowicz

def hash_round(d,rounds):
    x = hashlib.sha256(d).digest()
    r = x
    for i in range(rounds):
        r += ''.join(map(lambda x: chr((ord(x)+1)&0xff),r[:16]))
        x = hashlib.sha256(r).digest()
        r = x
    return x

def hash_resource(d):
    x = hash_round(d[:0x20],0x40+0x40)
    y = hash_round(d[0x20:0x30],0x40)[:0x10]
    return y,x

def decrypt(d):
    iv,key = hash_resource(d)
    return aes_decrypt(d[0x30:],iv,key)
    
def xor(x,y):
    if len(x)>len(y):
        y = y * (len(x)/len(y))
    return ''.join(map(lambda x: chr(ord(x[0])^ord(x[1])),zip(x,y)))

###
#

def dump_to_file(filename, data):
    with open(filename, 'wb') as f:
        f.write(data)
        
def main():
    parser = argparse.ArgumentParser(description="Dyreza payload decoder")
    parser.add_argument('--datafile',dest="datafile",default=None,help="File with data", required=True)
    parser.add_argument('--keyfile',dest="keyfile",default=None,help="File with xor keys", required=False)
    parser.add_argument('--outfile',dest="outfile",default="out.bin", help="Where to dump the output", required=False)
    args = parser.parse_args()

    data = open(args.datafile, 'rb').read()
    data_len = len(data)
    
    xorkeys = None
    if args.keyfile is not None:
        xorkeys = open(args.keyfile, 'rb').read()
    
    if len(data) == 0x30: #file with XOR keys
        print "This is the file with XOR keys. Use it as: --keyfile"
        return
        
    if xorkeys is None and len(data) % 0x10 == 0: #treat is as AES encrypted data
        print "AES encrypted data!"
        data = pad(data)
        output = decrypt(data)
        print len(output)
    else:
        if xorkeys is None:
            print "Supply the keyfile!"
            return
        output = xor(data, xorkeys)
        header = output[:2]
        if header == "\x00\x5b":
            print "xor decoding ok!"
            #output = decompress(output)
        else:
            print "xor decoding failed"
            output = data
            
    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)
        return
    print output

if __name__ == '__main__':
    main()
