Last active
April 3, 2020 23:32
-
-
Save dbeinder/74518726ae64ef0b964947e82fbbcf0f to your computer and use it in GitHub Desktop.
openssl enc hashcat poc
This file contains 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
# install requirements: pip3 install pycryptodome hashlib | |
import sys, os | |
from binascii import unhexlify, hexlify | |
from hashlib import md5, sha256 | |
from Crypto.Cipher import AES | |
# default setting, "openssl enc" pre v1.1.0 | |
def kdf_aes256_md5(pwd, salt): | |
h1 = md5(pwd + salt).digest() | |
h2 = md5(h1 + pwd + salt).digest() | |
iv = md5(h2 + pwd + salt).digest() | |
print("h1 = " + hexlify(h1).decode('ascii')) | |
print("h2 = " + hexlify(h2).decode('ascii')) | |
aes_key = h1 + h2 | |
return aes_key, iv | |
#default setting "openssl enc" since v1.1.0 | |
def kdf_aes256_sha256(pwd, salt): | |
h1 = sha256(pwd + salt).digest() | |
h2 = sha256(h1 + pwd + salt).digest() | |
print("h2 = " + hexlify(h2).decode('ascii')) | |
aes_key = h1 | |
iv = h2[:16] # first 16 bytes | |
return aes_key, iv | |
# usage: openssl_poc.py encrypted_file.aes "password_to_try" "known_header" | |
# all vars are raw bytes, there are no coversions to hex strings | |
password_to_try = sys.argv[2].encode() | |
known_header = sys.argv[3].encode() | |
with open(sys.argv[1], "rb") as f: | |
if f.read(8) != b"Salted__": | |
print("File " + sys.argv[1] + " is not a 'openssl enc' salted file, maybe it is base64 coded?") | |
sys.exit(-1) | |
file_salt = f.read(8) | |
first_block = f.read(16) | |
print("File: " + sys.argv[1]) | |
print("salt = " + hexlify(file_salt).decode('ascii')) | |
print("checking password [" + sys.argv[2] + "] = " + hexlify(password_to_try).decode('ascii')) | |
kdfs = { "OpenSSL 1.0.X default: MD5 / AES256": kdf_aes256_md5, | |
"OpenSSL 1.1.X default: SHA256 / AES256": kdf_aes256_sha256 } | |
for desc, kdf in kdfs.items(): | |
print("\n == " + desc + " ==") | |
aes_key, iv = kdf(password_to_try, file_salt) | |
print("aes_key = " + hexlify(aes_key).decode('ascii').upper()) | |
print("iv = " + hexlify(iv).decode('ascii').upper()) | |
aes = AES.new(aes_key, AES.MODE_CBC, iv) | |
first_block_plain = aes.decrypt(first_block) | |
pwd_is_good = first_block_plain[:len(known_header)] == known_header | |
print("password [" + sys.argv[2] + "] correct: " + str(pwd_is_good)) | |
print("last block decrypted: [" + str(first_block_plain) + "]") |
This file contains 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 | |
import sys, os | |
from binascii import unhexlify, hexlify | |
if len(sys.argv) != 3: | |
print("usage: openssl_tohash.py encrypted_file.aes known_header") | |
print(" Format: $opensslenc$salt*first_block*known_header") | |
sys.exit(-1) | |
try: | |
file_size = os.stat(sys.argv[1]).st_size | |
if file_size < 32: | |
print("File " + sys.argv[1] + " is not a 'openssl enc' salted file, can't be smaller than 32 bytes") | |
sys.exit(-1) | |
single_block = file_size == 32 | |
with open(sys.argv[1], "rb") as f: | |
if f.read(8) != b"Salted__": | |
print("File " + sys.argv[1] + " is not a 'openssl enc' salted file, maybe it is base64 coded?") | |
sys.exit(-1) | |
file_salt = f.read(8) | |
first_block = f.read(16) | |
except EnvironmentError as err: | |
print("Error reading file: " + str(err)) | |
sys.exit(-1) | |
outstr = "$opensslenc$" + hexlify(file_salt).decode('ascii') | |
outstr += "*" + hexlify(first_block).decode('ascii') | |
outstr += "*" + hexlify(sys.argv[2].encode()).decode('ascii') | |
print(outstr) | |
sys.exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment