1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
| #!/usr/bin/python
#############################################################################
## ##
## Quick script to decipher Bitcrypt encrypted files ##
## Some crypto routines have been ripped from open source projects ##
## ##
## Copyright (C) 2014 Airbus Defence and Space Cybersecurity ##
## ##
## Author: Fabien Perigaud ##
## ##
#############################################################################
import hashlib
import hmac
from struct import Struct
from operator import xor
from itertools import izip, starmap
from Crypto.Cipher import AES
from Crypto.Util import Counter
import sys
# Here are the broken keys. Feel free to add your own key here
known_keys = {
31298847196625400639506938637161930162789011464295952600544145829335849533528834917800088971765784757175491347320005860302574523:(4627583475399516037897017387039865329961620697520288948716924853,6763540271723193027434512605129229364869394444394656022641769391),
1070522051875563593553065099224464744659023600860372772781263109201150226305647551848134828908097626243245595520114791536742727:(1005626102545267712186089235734458416750943099190207256474703893,1064532880725791050651195212768400859770774190907227021360111339)
}
def decode_key(key):
base = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789+="
out = ''.join( [ "{0:06b}".format(base.find(k)) for k in key ] )
return int(out,2)
def inv(p, q):
"""Multiplicative inverse"""
def xgcd(x, y):
"""Extended Euclidean Algorithm"""
s1, s0 = 0, 1
t1, t0 = 1, 0
while y:
q = x // y
x, y = y, x % y
s1, s0 = s0 - q * s1, s1
t1, t0 = t0 - q * t1, t1
return x, s0, t0
s, t = xgcd(p, q)[0:2]
assert s == 1
if t < 0:
t += q
return t
def int2Text(number, size):
text = "".join([chr((number >> j) & 0xff)
for j in reversed(range(0, size << 3, 8))])
return text.lstrip("\x00")
def rsa_decrypt(text, sk, p, q):
mod = p * q
a = int(text.encode('hex'),16)
m1 = pow(a, sk % (p - 1), p)
m2 = pow(a, sk % (q - 1), q)
h = (inv(q, p) * (m1 - m2)) % p
b = m2 + h * q
return int2Text(b,64)
def pbkdf2_bin(data, salt, iterations=1000, keylen=0x32, hashfunc=None):
_pack_int = Struct('>I').pack
hashfunc = hashfunc or hashlib.sha1
mac = hmac.new(data, None, hashfunc)
def _pseudorandom(x, mac=mac):
h = mac.copy()
h.update(x)
return map(ord, h.digest())
buf = []
for block in xrange(1, -(-keylen // mac.digest_size) + 1):
rv = u = _pseudorandom(salt + _pack_int(block))
for i in xrange(iterations - 1):
u = _pseudorandom(''.join(map(chr, u)))
rv = starmap(xor, izip(rv, u))
buf.extend(rv)
return ''.join(map(chr, buf))[:keylen]
if len(sys.argv) != 2:
print "usage: %s <filename>" % sys.argv[0]
sys.exit(1)
try:
fn = open(sys.argv[1],"rb")
except:
print "[-] Error opening file %s" % sys.argv[1]
sys.exit(1)
data = fn.read()
fn.close()
try:
pub_key = data.split("<IDPubKey++>")[1].split("<IDPubKey-->")[0]
ciph_key = data.split("<AesRPass++>")[1].split("<AesRPass-->")[0]
data_len = int(data.split("<cfg++0>")[1].split("<cfg--0>")[0])
except:
print "[-] Error parsing file footer"
sys.exit(1)
print "[*] Pub key: %s" % pub_key
pub_key_int = decode_key(pub_key)
if pub_key_int not in known_keys:
print "[-] Unknown key"
print "[*] Try to break the following key using cado-nfs"
print pub_key_int
sys.exit(-1)
(p,q) = known_keys[pub_key_int]
print "[*] Ciphered AES key: %s" % ciph_key.encode("hex")
priv_key = inv(0x10001, (p-1)*(q-1))
dec_key = rsa_decrypt(ciph_key, priv_key, p, q)
aes_key = dec_key[-32:]
print "[+] AES Password: %s" % aes_key
blob = data.split("<cfg++0>")[0]
if len(blob) != data_len:
print "[-] Incorrect data len"
sys.exit(1)
iv = blob[:12]
pwd_verif = blob[12:14]
vhmac = blob[-10:]
ciph_data = blob[14:-10]
derived_key = pbkdf2_bin(aes_key, iv, 1000, 0x32)
aes_key = derived_key[:24]
hmac_key = derived_key[24:48]
print "[+] Derived AES Key: %s" % aes_key.encode('hex')
if pwd_verif == derived_key[-2:]:
print "[+] Key is correct"
else:
print "[-] Key is incorrect"
sys.exit(1)
mac = hmac.new(hmac_key, None, hashlib.sha1)
mac.update(ciph_data)
if mac.digest()[:10] == vhmac:
print "[+] Ciphered text hmac is correct"
else:
print "[-] Ciphered text hmac is incorrect"
sys.exit(1)
ctr = Counter.new(128, little_endian=True)
cipherCTR = AES.new(aes_key, AES.MODE_CTR, counter = ctr)
cleartext = cipherCTR.decrypt(ciph_data)
print "[+] Decryption done. Output in \"%s.clear\"" % sys.argv[1]
try:
fout = open(sys.argv[1]+".clear","wb")
except:
print "[-] Could not open output file"
sys.exit(1)
data = fout.write(cleartext)
fn.close() |
Partager