VirtualBox Disk Image Encryption password cracker
Julio 15, 2015
VirtualBox 5.0 was released the past July 9 with a new built-in disk image encryption feature which allows the user to encrypt virtual hard disk transparently.
With this feature a new tab is enabled in General configuration for each machine:
When the user sets a password, a new element called Property is added to the HardDisk element inside the machine configuration:
<Property name="CRYPT/KeyId" value="Encrypted"/>
<Property name="CRYPT/KeyStore"
value="U0NORQABQUVTLVhUUzEyOC1QTEFJTjY0AAAAAAAAAAAAAAAAAABQQktERjItU0hB
MjU2AAAAAAAAAAAAAAAAAAAAAAAAACAAAAAJwd3SksjYgaKyVqNkFvSNya8SkGiz
kfuKYCB2xJk67SAAAACbTjDwMkoPESRduJWBXP4U+Tmtm3lj1k6kBlgeB42/NtAH
AACdTMPxXmuA+fiTrKHvuS+xFrYcbGj6SDa4uiUWV9WCU9AHAAAgAAAAq/tmzFGv
wmcIaYYgDxJidNRFk71JTjqUaKXS2wMuDVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAA=="/>
</HardDisk>
The KeyStore is encoded using Base64, and it contains the information needed by the machine to verify the password each time the user wants to start a machine or change its password.
I made a tool called VBOXDIECracker as a proof of concept to crack weak passwords used in this new feature of VirtualBox, you can download it from:
https://github.com/sinfocol/vboxdie-cracker/
Following is a detailed explanation of how this new feature works:
KeyStore Format
First, we need to identify in someway the fields within the decoded keystore:
0000h: 53 43 4E 45 00 01 41 45 53 2D 58 54 53 32 35 36 SCNE..AES-XTS256 0010h: 2D 50 4C 41 49 4E 36 34 00 00 00 00 00 00 00 00 -PLAIN64........ 0020h: 00 00 00 00 00 00 50 42 4B 44 46 32 2D 53 48 41 ......PBKDF2-SHA 0030h: 32 35 36 00 00 00 00 00 00 00 00 00 00 00 00 00 256............. 0040h: 00 00 00 00 00 00 40 00 00 00 12 02 78 97 DA CB ......@.....x—ÚË 0050h: 3A 4C 4F EE F4 87 62 9D 68 A0 73 00 20 D9 B5 DE :LOîô‡b h s. ÙµÞ 0060h: 74 94 40 8C 7A F9 9A F0 82 89 20 00 00 00 27 B5 t”@Œzùšð‚‰ ...'µ 0070h: 01 C3 16 F4 9F C2 96 B2 FE 32 85 57 35 16 73 81 .Ã.ôŸÂ–²þ2…W5.s. 0080h: AC 20 9F D1 C0 C8 3E 5E 41 B6 6F F3 C3 5A D0 07 ¬ ŸÑÀÈ>^A¶oóÃZÐ. 0090h: 00 00 8A 8F 4A 94 83 7E EC 1B B4 D6 9A 2E 7C 9F ..Š J”ƒ~ì.´Öš.|Ÿ 00A0h: FA DC 5E 65 95 36 DF 45 A8 1C 46 66 2C F6 6B E9 úÜ^e•6ßE¨.Ff,öké 00B0h: 5E 58 D0 07 00 00 40 00 00 00 EA A5 55 F2 73 AE ^XÐ...@...ê¥Uòs® 00C0h: AF 9F 11 57 12 8F D1 C3 51 7D 7C AE F4 3E C9 AA ¯Ÿ.W. ÑÃQ}|®ô>ɪ 00D0h: A5 40 69 17 CD 13 72 C5 76 8C F8 85 7C 56 59 67 ¥@i.Í.rÅvŒø…|VYg 00E0h: 31 8C E1 81 24 0F C1 43 95 6E C2 FA C3 C4 EF 0E 1Œá $.ÁC•nÂúÃÄï. 00F0h: 62 9C 18 82 5D F2 28 E7 1E C2 bœ.‚]ò(ç.Â
After some work we are able to identify each field:
Offset | Bytes | Description |
---|---|---|
0 | 4 | File header signature = 0x454E4353 (SCNE) |
4 | 2 | Version |
6 | 32 | EVP algorithm |
38 | 32 | PBKDF2 hash algorithm |
70 | 4 | Generic key length (used by PBKDF2 and AES-XTS) |
74 | 32 | Final hash where comparison is done |
106 | 4 | Key length used in the second call to PBKDF2 |
110 | 32 | Salt used in the second call to PBKDF2 |
142 | 4 | Iterations used in the second call to PBKDF2 |
146 | 32 | Salt used in the first call to PBKDF2 |
178 | 4 | Iterations used in the first call to PBKDF2 |
182 | 4 | EVP input length |
186 | 64 | Encrypted password used in the second call to PBKDF2 (to be used as input in the call to AES-XTS) |
VirtualBox Keystore 010 editor template
The following 010 Editor template could be used as a guide:
//--- 010 Editor v6.0.2 Binary Template
//
// File: VBOXDIEKeyStore.bt
// Author: Daniel Correa
// URL: http://www.sinfocol.org/
// Revision: 1.0
// Purpose: Template for VirtualBox Disk Image Encryption KeyStore
//--------------------------------------
typedef struct vbox_die_keystore {
int header <bgcolor=0xaabbcc, format=hex, name="Header">;
if (header != 0x454E4353) {
SetBackColor(0x0000ff);
Warning("File is not a valid VBOX DIE KeyStore. Bad signature.");
return -1;
}
uint16 version <bgcolor=0xccddee, name="Version">;
char algorithm[32] <bgcolor=0x00ffee, name="EVP encryption algorithm">;
char kdf[32] <bgcolor=0xffbbee, name="Key derivation function hash algorithm">;
int generic_key_length <bgcolor=0x3399ee, name="Generic key length">;
char final_hash[32] <bgcolor=0x4444ff, name="Final hash">;
int pbkdf2_2_key_length <bgcolor=0x3399ee, name="Second PBKDF2 key length">;
char pbkdf2_2_salt[32] <bgcolor=0x999999, name="Second PBKDF2 salt">;
int pbkdf2_2_iterations <bgcolor=0xaa9933, name="Second PBKDF2 iterations">;
char pbkdf2_1_salt[32] <bgcolor=0x999999, name="First PBKDF2 salt">;
int pbkdf2_1_iterations <bgcolor=0xaa9933, name="First PBKDF2 iterations">;
int evp_decrypt_input_length <bgcolor=0x3399ee, name="EVP decrypt input length">;
char pbkdf2_2_encrypted_password[64] <bgcolor=0xff7777, name="Second PBKDF2 encrypted password">;
};
FSeek(0);
LittleEndian();
vbox_die_keystore VBOXDIE;
The result of running the template:
VirtualBox password storage algorithm
With the identification of the fields within the keystore we can now have an understanding of how the password storage algorithm works, and it is summarized in this way:
# 32 for AES-XTS128-PLAIN64
# 64 for AES-XTS256-PLAIN64
AES_key_length = 32 | 64
-------------------------
AES-password = PBKDF2(algorithm: SHA256,
password: user_password,
salt: random_salt_1,
iterations: 2000,
output_length: AES_key_length)
----------------------------------------------
PBKDF2-decrypted-password = AES_decrypt(key_size: AES_key_length,
mode: XTS,
data: random_data
password: AES-password,
type: raw,
iv: NULL)
-------------------------------------
Stored_hash = PBKDF2(algorithm: SHA256,
password: PBKDF2-decrypted-password,
salt: random_salt_2,
iterations: 2000,
output_length: 32)
The same process is performed each time the user wants to decrypt the machine disk. The stored hash (the one from keystore) is compared with the computed hash (the one from user input) in order to authenticate the user and let him use the machine.
VBOXDIECracker - the tool
With the appropriate format and algorithm we can emulate the password verification of VirtualBox and make a not-so-fast cracker with PHP (sorry guys, I did not find a standard package on python to use AES XTS), it is just a proof of concept, so you can develop another leet tools.
You can download it from this site or browse it from the repository.
This is a sample of the source code showing the main function which is the one who computes the final hash:
// redacted
/**
* crack_keystore
*
* Makes a bruteforce to find the final hash contained in the KeyStore
* Returns the plaintext password used to encrypt de disk of the virtual machine
*/
function crack_keystore($keystore, $wordlist) {
$fp = fopen($wordlist, 'r');
if (is_resource($fp)) {
$hash = get_hash_algorithm($keystore);
$method = get_openssl_method($keystore);
while (!feof($fp)) {
$user_password = trim(fgets($fp));
$EVP_password = hash_pbkdf2($hash, $user_password, $keystore['pbkdf2_1_salt'], $keystore['pbkdf2_1_iterations'], $keystore['generic_key_length'], true);
$decrypted_password = openssl_decrypt(substr($keystore['pbkdf2_2_encrypted_password'], 0, $keystore['evp_decrypt_input_length']), $method, $EVP_password, OPENSSL_RAW_DATA, '');
if ($decrypted_password === false) {
continue;
}
$final_hash = hash_pbkdf2($hash, $decrypted_password, $keystore['pbkdf2_2_salt'], $keystore['pbkdf2_2_iterations'], $keystore['pbkdf2_2_key_length'], true);
if ($final_hash === $keystore['final_hash']) {
return $user_password;
}
}
return false;
} else {
return false;
}
}
// redacted
And the final output with a recovered password:
$ php VBOXDIECracker.php VirtualBox Disk Image Encryption cracker Usage: VBOXDIECracker.php disk_image.vbox [wordlist] $ php VBOXDIECracker.php Encrypted.vbox wordlist.txt VirtualBox Disk Image Encryption cracker [+] Reading data from: Encrypted.vbox ---------------------------------------------------------------- [+] Checking hard disk encryption for: Encrypted.vdi [+] Hard disk is encrypted [+] KeyStore encoded string: U0NORQABQUVTLVhUUzI1Ni1QTEFJTjY0AAAAAAAAAAAAAAAAAABQQktERjItU0hB MjU2AAAAAAAAAAAAAAAAAAAAAAAAAEAAAAASAniX2ss6TE/u9IdinWigcwAg2bXe dJRAjHr5mvCCiSAAAAAntQHDFvSfwpay/jKFVzUWc4GsIJ/RwMg+XkG2b/PDWtAH AACKj0qUg37sG7TWmi58n/rcXmWVNt9FqBxGZiz2a+leWNAHAABAAAAA6qVV8nOu r58RVxKP0cNRfXyu9D7JqqVAaRfNE3LFdoz4hXxWWWcxjOGBJA/BQ5VuwvrDxO8O YpwYgl3yKOcewg== [+] KeyStore contents: Header 454e4353 (SCNE) Version 1 Algorithm AES-XTS256-PLAIN64 KDF PBKDF2-SHA256 Key length 64 Final hash 12027897dacb3a4c4feef487629d68a0730020d9b5de7494408c7af99af08289 PBKDF2 2 Key length 32 PBKDF2 2 Salt 27b501c316f49fc296b2fe32855735167381ac209fd1c0c83e5e41b66ff3c35a PBKDF2 2 Iterations 2000 PBKDF2 1 Salt 8a8f4a94837eec1bb4d69a2e7c9ffadc5e659536df45a81c46662cf66be95e58 PBKDF2 1 Iterations 2000 EVP buffer length 64 PBKDF2 2 encrypted password eaa555f273aeaf9f1157128fd1c3517d7caef43ec9aaa5406917cd1372c5768c f8857c565967318ce181240fc143956ec2fac3c4ef0e629c18825df228e71ec2 [+] Cracking finished, measured time: 6.13035 seconds [!] KeyStore password found: 123 ---------------------------------------------------------------- [+] Checking hard disk encryption for: New_Disk.vdi [-] Hard disk is not encrypted
Archivado en: Sin categoría |
Great work!
Guys like you make us safer, understanding not to use easy to crack methods.
THANK YOU!
It seems to me that without a wordlist.txt or while using a complex password (that is not part of the wordlist.txt ) your tool won't work. Am I wrong ?
This is now handled also by John ripper.