Open trounce1 opened 4 years ago
https://dspace.cvut.cz/bitstream/handle/10467/69601/F8-BP-2017-Vojtesek-Jan-thesis.pdf could be helpful.
Update: Related source-code can be found at the following URL,
I saw this the other day, I compiled it and read through source. It is a program to parse an optional recovery file and the virtually mount and decrypt the volume. I couldn’t find anywhere about the header of an FDE disk.
This is what the header looks like.
the first 32 bytes appear to also be present in the s-table for blowfish
I have written a proof of concept based on the above paper.
from binascii import hexlify
import hashlib
from Crypto.Cipher import AES
from sys import argv
from CryptoPlus.Cipher import python_Rijndael
buffsize = 0x10000
buff = b''
password = b'password'
bc_file = open(argv[1], 'rb').read(0x588300)
salt = bc_file[488:496]
enc_data = bc_file[38:134]
encrypted_first_sector = bc_file[0x588100:0x588300]
while len(buff) < buffsize:
buff += salt
buff += password
dk = hashlib.sha256(buff).digest()
cipher = AES.new(dk, AES.MODE_CBC, b'\0' * 16)
plain = cipher.decrypt(enc_data)
hash_of_keys = hashlib.sha256(plain[:0x40]).digest()
primary_key = plain[:0x20]
tweak = plain[0x20:0x40]
hashval = plain[0x40:]
print('primary key : ', hexlify(primary_key))
print('tweak key : ', hexlify(tweak))
print('hash value : ', hexlify(hashval))
print('hash of keys : ', hexlify(hash_of_keys))
if hash_of_keys == hashval:
key = (primary_key, tweak)
cipher2 = python_Rijndael.new(key, python_Rijndael.MODE_XTS, blocksize=16)
decrypted_first_sector = cipher2.decrypt(encrypted_first_sector)
print('Encrypted First Sector : ', hexlify(encrypted_first_sector[:0x40]))
print('Decrypted First Sector : ', hexlify(decrypted_first_sector[:0x40]))
this works on the old versions of bestcrypt full disk. it does not work on modern versions v4+
attached is the partial image that works : partial_image.bin.zip
Update : Added decryption of first block
@kholia!!! 🎉
I missed you
@trounce1 Here is a plan:
Let's add support for old versions of BCVE for now (you know how to do this already).
Figure out how the author(s) did their original reversing work. This is hard and I struggle with it. I get 1 or 2 hours of free time a day and I am already tired by then (heh). Try https://www.ghidra-sre.org/ for RE work.
Follow their footsteps and figure out the new changes in v4+ (newer KDF? different iterations? different offsets in the header? different default crypto?).
@MotherOfAllVoids Thanks for your awesome thesis work on reversing BCVE. Do you remember which files you reverse engineered and the general process you used? Thanks!
looks like it is now scrypt as see in url below https://www.jetico.com/file-downloads/web_help/bcve4/?url=html/02_standards/01_security_characteristics.htm
ive tried a few things with scrypt and camellia but to no avail.
i thought about reversing the 16 bit recovery binary that comes with the recovery disk as it is small ~500kb. i cant seem to find anything that will decompile 16bit x86
I cant seem to find anything that will decompile 16bit x86.
GHIDRA seems to be working fine for recovery.exe
. Give it a try.
GHIDRA (+ https://github.com/d3v1l401/FindCrypt-Ghidra) in action:
It seems recovery.exe
doesn't support v4.x volumes?
good spot, It now looks like they are using scrypt with a 5 digit iteration count after talking to their support team. i will need to confirm the settings.
Hey guys,
the thesis linked above only deals with BCVE v3 (since v4 wasn't out yet) and I didn't really look into v4 since release. However, the weak password hashing algorithm (cracking the password in v3 basically boils down to trying single iterations of SHA256) was one of the things that I reported to Jetico and they told me that they were already planning to improve it, most likely by using scrypt.
If you are looking for the headers as they are on the raw disk, they are described in another thesis at my university done by Juraj Hornak (https://dspace.cvut.cz/handle/10467/65108?show=full). Unfortunately, it's in Slovak, but I hope that it still can help... The table on page 29 describes exactly what you have in the hex dump above. The first 32 bytes, are just magic bytes, they are derived from digits of Pi, same as blowfish sboxes, so it's pretty much just coincidence :). What you are probably interested in are the 0x60 bytes from offset 0x26 to offset 0x86.
I worked by reverse engineering the main usermode binary and attaching a debugger to it a lot. Since you already found the implementation of SHA256, I think it'll be easiest to just go through all of its uses and you should find the password hashing routine, but yeah, it'll probably not be easy :).
@janvojtesek good info. thanks for the paper. i have translated F8-DP-2016-Hornak-Juraj-thesis.cs.en.pdf
Update: My code a few comments above uses those offsets you talk about.
Was there any way to distinguish the version number of the BCVE?
Was there any way to distinguish the version number of the BCVE?
I can help with this I think.
Update: Probably not :|
good spot, It now looks like they are using scrypt with a 5 digit iteration count after talking to their support team. i will need to confirm the settings.
the scrypt parameters are p=1, r=16, N=32768 or 2^15
it differs now from my script as apparently the encryption algorithm to derive to volume keys is the same one used to decrypt the volume.
e.g. you encrypt your disk with aes-xts and also decrypt the 0x60 bytes from offset 0x26 to offset 0x86 with aes-xts.
GHIDRA seems to be working fine for recovery.exe.
Surprisingly IDA's dissembler output is easier to read than GHIDRA's decompiler output. IDA handles string references pretty well.
GHIDRA seems to be working fine for recovery.exe.
Surprisingly IDA's dissembler output is easier to read than GHIDRA's decompiler output. IDA handles string references pretty well.
I noticed the same thing. did you find any reference to 2^15?
did you find any reference to 2^15?
Perhaps the called function (at 004da2f0
) is the scrypt function or leads to it?
https://github.com/technion/libscrypt/blob/master/crypto_scrypt-nosse.c <-- The next step would be to find code patterns (in the binary to be reversed) similar to this .c
file?
Also,
Seems like we are on the right track (?).
I entered xyzabc
as the password.
did you find any reference to 2^15?
Perhaps the called function (at
004da2f0
) is the scrypt function or leads to it?https://github.com/technion/libscrypt/blob/master/crypto_scrypt-nosse.c <-- The next step would be to find code patterns (in the binary to be reversed) similar to this
.c
file?Also,
Seems like we are on the right track (?).
I entered
xyzabc
as the password.
Thats great progress. im pretty sure this is the implementation for V4 format, something is missing though.
from binascii import hexlify
from sys import argv
import scrypt
from CryptoPlus.Cipher import python_Rijndael
password = b'password'
bc_file = open(argv[1], 'rb').read(0x588300)
salt = bc_file[0x1e8:0x1f0]
enc_data = bc_file[0x26:0x86]
encrypted_first_sector = bc_file[0x588100:0x588300]
p = 1
r = 16
N = pow(2, 15)
derived_first_key = scrypt.hash(password, salt, N, r, p)
first_aes_primary_key = derived_first_key[:0x20]
first_aes_tweak_key = derived_first_key[0x20:]
key = (first_aes_primary_key, first_aes_tweak_key)
cipher = python_Rijndael.new(key, python_Rijndael.MODE_XTS, blocksize=16)
decrypted_data = cipher.decrypt(enc_data)
hash_of_keys = scrypt.hash(decrypted_data[:0x40], b'', N, r, p, 0x20)
hashval = decrypted_data[0x40:]
print('first scrypt : ', hexlify(derived_first_key))
print('first primary key : ', hexlify(first_aes_primary_key))
print('first tweak key : ', hexlify(first_aes_tweak_key))
print('hash value : ', hexlify(hashval))
print('hash of keys : ', hexlify(hash_of_keys))
if hash_of_keys == hashval:
print('correct_password')
I am sharing a copy of an encrypted v4 disk. Might be helpful in debugging and in comparing notes.
https://github.com/kholia/bcve_otfe/blob/master/src/bcve_otfe/encrypted.raw.zip
Password is "openwall".
For this image:
In [9]: f = open("encrypted.raw", "rb").read(512000)
In [10]: f.rfind(b"\x4b\x9e\x5d\x53")
Out[10]: 32744
In [11]: binascii.hexlify(f[32744:32744+32])
Out[11]: b'4b9e5d53ba3dbb6a08100000000000000000000000000000f05292fcc3154625'
In [12]: binascii.hexlify(f[32744:32744+8])
Out[12]: b'4b9e5d53ba3dbb6a'
I suspect that the v4 program is using a bigger salt somehow? Look at the hexdump (pointing to the salt buffer) in my debugger screenshot.
Also,
In [16]: f.find(b"\x1a\x0c\x40\xc9\xf1\x85")
Out[16]: 32614
In [17]: binascii.hexlify(f[32614:32614+32])
Out[17]: b'1a0c40c9f185c9aef9fc63f4561c96a310100000000000000404000000000000
This is the "salt continuation" sub-string we saw in the debugger screenshot.
I suspect that the v4 program is using a bigger salt somehow?
Confirmed.
$ cat code.py
# Demo
from binascii import hexlify
from sys import argv
import scrypt
#from CryptoPlus.Cipher import python_Rijndael
import binascii
password = b'xyzabc'
#bc_file = open(argv[1], 'rb').read(0x588300)
#salt = bc_file[0x1e8:0x1f0]
#salt = bc_file[0x1e8:0x1f0]
salt = "4b9e5d53ba3dbb6a" + "1a0c40c9f185c9aef9fc63f4561c96a3" # latter is "salt continuation"
salt = binascii.unhexlify(salt)
#enc_data = bc_file[0x26:0x86]
#encrypted_first_sector = bc_file[0x588100:0x588300]
p = 1
r = 16
N = pow(2, 15)
derived_first_key = scrypt.hash(password, salt, N, r, p)
print(binascii.hexlify(derived_first_key))
This programs outputs b'3b43545d86b4e24b0870...
. This is exactly the "key" that is also calculated by the target program (see Dump 2
in the screenshot below).
I suspect that the v4 program is using a bigger salt somehow?
Confirmed.
$ cat code.py # Demo from binascii import hexlify from sys import argv import scrypt #from CryptoPlus.Cipher import python_Rijndael import binascii password = b'xyzabc' #bc_file = open(argv[1], 'rb').read(0x588300) #salt = bc_file[0x1e8:0x1f0] #salt = bc_file[0x1e8:0x1f0] salt = "4b9e5d53ba3dbb6a" + "1a0c40c9f185c9aef9fc63f4561c96a3" # latter is "salt continuation" salt = binascii.unhexlify(salt) #enc_data = bc_file[0x26:0x86] #encrypted_first_sector = bc_file[0x588100:0x588300] p = 1 r = 16 N = pow(2, 15) derived_first_key = scrypt.hash(password, salt, N, r, p) print(binascii.hexlify(derived_first_key))
This programs outputs
b'3b43545d86b4e24b0870...
. This is exactly the "key" that is also calculated by the target program (seeDump 2
in the screenshot below).
amazin, so just need to work out how it calculates the salt and we are there
I can extract the full salt from the encrypted disks - not a problem.
The following code needs to be validated.
enc_data = bc_file[0x26:0x86]
...
first_aes_primary_key = derived_first_key[:0x20]
first_aes_tweak_key = derived_first_key[0x20:]
key = (first_aes_primary_key, first_aes_tweak_key)
cipher = python_Rijndael.new(key, python_Rijndael.MODE_XTS, blocksize=16)
decrypted_data = cipher.decrypt(enc_data)
hash_of_keys = scrypt.hash(decrypted_data[:0x40], b'', N, r, p, 0x20)
hashval = decrypted_data[0x40:]
print('first scrypt : ', hexlify(derived_first_key))
print('first primary key : ', hexlify(first_aes_primary_key))
print('first tweak key : ', hexlify(first_aes_tweak_key))
print('hash value : ', hexlify(hashval))
print('hash of keys : ', hexlify(hash_of_keys))
if hash_of_keys == hashval:
print('correct_password')
I am having trouble with this code, right from the enc_data
extraction part.
Quick notes:
I am now trying to locate the higher level AES decryption code and XTS code. The idea is to see what data it is trying to decrypt.
Quick notes:
- AES is located at 0x4CDBF0. <-- This could be "AES Key Expansion".
I am now trying to locate the higher level AES decryption code and XTS code. The idea is to see what data it is trying to decrypt.
and what the keys / tweak keys might be being used
The idea is to see what data it is trying to decrypt.
Found the data + it's offset.
In [45]: f.find(b"\xab\xf1\xcc\x52")
Out[45]: 32294
This screenshot shows the call to the decryption function and the disk data it is decrypting.
The idea is to see what data it is trying to decrypt.
Found the data + it's offset.
In [45]: f.find(b"\xab\xf1\xcc\x52") Out[45]: 32294
This screenshot shows the call to the decryption function and the disk data it is decrypting.
yeah thats the same. you are looking at the full disk rather than the partition. your offset is 0x7e00 + the script offsets. ill write a quick patch on my script to account for this
The idea is to see what data it is trying to decrypt.
Found the data + it's offset.
In [45]: f.find(b"\xab\xf1\xcc\x52") Out[45]: 32294
This screenshot shows the call to the decryption function and the disk data it is decrypting.
yeah thats the same. you are looking at the full disk rather than the partition. your offset is 0x7e00 + the script offsets. ill write a quick patch on my script to account for this
password = b'xyzabc'
bc_file = open(argv[1], 'rb').read(0x588300)
offset = 0
if bc_file[0x1fe:0x200] == b'\x55\xaa':
offset = 0x200 * struct.unpack('<i', bc_file[0x1c6:0x1ca])[0]
salt = bc_file[offset + 0x1e8:offset + 0x1f0] + bc_file[offset + 0x166:offset + 0x176]
enc_data = bc_file[offset + 0x26:offset + 0x86]
encrypted_first_sector = bc_file[offset + 0x588100:offset + 0x588300]
add that to your code, your first sector may vary
Thanks.
I am trying to trace this function now:
signed int __cdecl sub_4D2560(_DWORD *key, int n_8, int input_known, int output_likely)
{
char *v4; // ecx
_DWORD *v5; // ebx
unsigned int v6; // edx
bool v7; // cf
int v9; // [esp+8h] [ebp-34h]
int v10; // [esp+Ch] [ebp-30h]
int v11; // [esp+10h] [ebp-2Ch]
int v12; // [esp+14h] [ebp-28h]
char v13; // [esp+18h] [ebp-24h]
v9 = 0;
v10 = 0;
v11 = 0;
v12 = 0;
setup_keys_init(n_8, key, &ctx);
is_this_xts_decrypt(n_8, input_known, output_likely, 96u, (int)&v9, 0, (int)&ctx, 0);
simple_sha256_or_something_else(output_likely, 64u, (int)&v13);
v4 = &v13;
v5 = (_DWORD *)(output_likely + 64);
v6 = 28;
while ( *v5 == *(_DWORD *)v4 )
{
++v5;
v4 += 4;
v7 = v6 < 4;
v6 -= 4;
if ( v7 )
return 1;
}
return 0;
}
The input_known
has the data (enc_data
) from above screenshot. The scrypt key is getting calculated fine and is being passed to this function.
The next problem is that the decrypted data (for enc_data
encrypted input) doesn't match between this target program and our Python code below.
derived_first_key = scrypt.hash(password, salt, N, r, p)
print(binascii.hexlify(derived_first_key))
print(len(derived_first_key))
first_aes_primary_key = derived_first_key[:0x20]
first_aes_tweak_key = derived_first_key[0x20:]
key = (first_aes_primary_key, first_aes_tweak_key)
#print(len(first_aes_tweak_key))
#print(len(first_aes_primary_key))
cipher = python_Rijndael.new(key, python_Rijndael.MODE_XTS, blocksize=16)
decrypted_data = cipher.decrypt(enc_data)
print(decrypted_data)
print(hexlify(decrypted_data))
Not sure what is_this_xts_decrypt
is doing with enc_data
. I know that AES Key Expansion
is getting called twice which happens in XTS mode.
case 8: // TANGO! Setup two keys for XTS?
aes_key_expansion(key_, v3);
sub_4CD0E0(key_, v3 + 61);
aes_key_expansion(key_ + 8, v3 + 122);
result = 1;
break;
@trounce1 Can you please share your full encrypted image? I will attach it to this debugging VM and step through the target program.
@trounce1 Can you please share your full encrypted image? I will attach it to this debugging VM and step through the target program.
This also has my rescue file in it which should also contain the same 0x60 bytes The password is password
I know that
AES Key Expansion
is getting called twice which happens in XTS mode.
With better comments,
case 8: // TANGO! Setup two keys for XTS?
// https://github.com/magnumripper/JohnTheRipper/blob/bleeding-jumbo/src/xts_plug.c#L25
AES_key_expansion_likely(key_, mystery_struct);
AES_encrypt(key_, (_DWORD *)mystery_struct + 61);
AES_key_expansion_likely(key_ + 32, (_DWORD *)mystery_struct + 122);
result = 1;
break;
Note: This code is at 004D3C8B
location.
This still doesn't explain why our XTS decryption stuff is not working well. Hmmm.
Current Code:
# Demo Code (BCVE v4)
from binascii import hexlify
from sys import argv
import scrypt
import binascii
import hashlib
import struct
from CryptoPlus.Cipher import python_Rijndael
from Crypto.Cipher import AES
password = b'openwall'
bc_file = open(argv[1], 'rb').read(0x588300)
if bc_file[0x1fe:0x200] == b'\x55\xaa':
offset = 0x200 * struct.unpack('<i', bc_file[0x1c6:0x1ca])[0]
print(offset)
# old kdf - program still tries it!
"""
salt = bc_file[offset + 0x1e8:offset + 0x1f0]
buffsize = 0x10000
buff = b''
while len(buff) < buffsize:
buff += salt
buff += password
dk = hashlib.sha256(buff).digest()
print(hexlify(dk)) # EB FA E9... the target exe calculates this too!
print(hexlify(dk[15:])) # EB FA E9... the target exe calculates this too!
"""
salt = bc_file[offset + 0x1e8:offset + 0x1f0] + bc_file[offset + 0x166:offset + 0x176]
enc_data = bc_file[offset + 0x26:offset + 0x86]
encrypted_first_sector = bc_file[offset + 0x588100:offset + 0x588300]
print(hexlify(enc_data))
p = 1
r = 16
N = pow(2, 15)
derived_first_key = scrypt.hash(password, salt, N, r, p)
print(binascii.hexlify(derived_first_key))
first_aes_primary_key = derived_first_key[:0x20]
first_aes_tweak_key = derived_first_key[0x20:]
key = (first_aes_primary_key, first_aes_tweak_key)
cipher = python_Rijndael.new(key, python_Rijndael.MODE_XTS, blocksize=16)
decrypted_data = cipher.decrypt(enc_data)
print(decrypted_data)
print(hexlify(decrypted_data))
# hash_of_keys = scrypt.hash(decrypted_data[:0x40], b'', N, r, p, 0x20)
hash_of_keys = hashlib.sha256(decrypted_data[:64]).digest()
hashval = decrypted_data[64:96]
print('first scrypt : ', hexlify(derived_first_key))
print('first primary key : ', hexlify(first_aes_primary_key))
print('first tweak key : ', hexlify(first_aes_tweak_key))
print('hash value : ', hexlify(hashval))
print('hash of keys : ', hexlify(hash_of_keys))
if hash_of_keys == hashval:
print('correct_password')
We just need to debug the data decryption part. Taking a break for now :)
Current Code:
# Demo Code (BCVE v4) from binascii import hexlify from sys import argv import scrypt import binascii import hashlib import struct from CryptoPlus.Cipher import python_Rijndael from Crypto.Cipher import AES password = b'openwall' bc_file = open(argv[1], 'rb').read(0x588300) if bc_file[0x1fe:0x200] == b'\x55\xaa': offset = 0x200 * struct.unpack('<i', bc_file[0x1c6:0x1ca])[0] print(offset) # old kdf - program still tries it! """ salt = bc_file[offset + 0x1e8:offset + 0x1f0] buffsize = 0x10000 buff = b'' while len(buff) < buffsize: buff += salt buff += password dk = hashlib.sha256(buff).digest() print(hexlify(dk)) # EB FA E9... the target exe calculates this too! print(hexlify(dk[15:])) # EB FA E9... the target exe calculates this too! """ salt = bc_file[offset + 0x1e8:offset + 0x1f0] + bc_file[offset + 0x166:offset + 0x176] enc_data = bc_file[offset + 0x26:offset + 0x86] encrypted_first_sector = bc_file[offset + 0x588100:offset + 0x588300] print(hexlify(enc_data)) p = 1 r = 16 N = pow(2, 15) derived_first_key = scrypt.hash(password, salt, N, r, p) print(binascii.hexlify(derived_first_key)) print(len(derived_first_key)) first_aes_primary_key = derived_first_key[:0x20] first_aes_tweak_key = derived_first_key[0x20:] key = (first_aes_primary_key, first_aes_tweak_key) #print(len(first_aes_tweak_key)) #print(len(first_aes_primary_key)) cipher = python_Rijndael.new(key, python_Rijndael.MODE_XTS, blocksize=16) decrypted_data = cipher.decrypt(enc_data) print(decrypted_data) print(hexlify(decrypted_data)) # hash_of_keys = scrypt.hash(decrypted_data[:0x40], b'', N, r, p, 0x20) hash_of_keys = hashlib.sha256(decrypted_data[:64]).digest() hashval = decrypted_data[64:96] print('first scrypt : ', hexlify(derived_first_key)) print('first primary key : ', hexlify(first_aes_primary_key)) print('first tweak key : ', hexlify(first_aes_tweak_key)) print('hash value : ', hexlify(hashval)) print('hash of keys : ', hexlify(hash_of_keys)) if hash_of_keys == hashval: print('correct_password')
We just need to debug the data decryption part. Taking a break for now :)
you think they are using sha256 at the end?
i have solved it !!!
from binascii import hexlify
from sys import argv
import scrypt
import struct
from hashlib import sha256
from Crypto.Cipher import AES
password = b'password'
bc_file = open(argv[1], 'rb').read(0x588300)
offset = 0
if bc_file[0x1fe:0x200] == b'\x55\xaa':
offset = 0x200 * struct.unpack('<i', bc_file[0x1c6:0x1ca])[0]
salt = bc_file[offset + 0x1e8:offset + 0x1f0] + bc_file[offset + 0x166:offset + 0x176]
enc_data = bc_file[offset + 0x26:offset + 0x86]
encrypted_first_sector = bc_file[offset + 0x588100:offset + 0x588300]
p = 1
r = 16
N = pow(2, 15)
derived_first_key = scrypt.hash(password, salt, N, r, p)
first_aes_primary_key = derived_first_key[:0x20]
cipher = AES.new(first_aes_primary_key, AES.MODE_CBC, b'\0' * 16)
decrypted_data = cipher.decrypt(enc_data)
hash_of_keys = sha256(decrypted_data[:0x40]).digest()
hashval = decrypted_data[0x40:]
print('first scrypt : ', hexlify(derived_first_key))
print('first primary key : ', hexlify(first_aes_primary_key))
print('hash value : ', hexlify(hashval))
print('hash of keys : ', hexlify(hash_of_keys))
Awesome! :) :) :)
Confirmation that SHA256 is being used.
How did you figure out the cipher = AES.new(first_aes_primary_key, AES.MODE_CBC, b'\0' * 16)
part?
The code was somehow indicating XTS mode usage (maybe it was already decrypting the first sector in the debugger and not just the initial verification header!?).
How did you figure out the
cipher = AES.new(first_aes_primary_key, AES.MODE_CBC, b'\0' * 16)
part?The code was somehow indicating XTS mode usage (maybe it was already decrypting the first sector in the debugger and not just the initial verification header!?).
i just gave it a go and assumed that it hadnt changed. A kernel can now be written. ill do some research into the other 2 crypto algorithms that can be used and see if the behaviour is the same.
I did notice 16 NULL bytes in the debugger near AES code. Should have guessed a Zero IV. Doh! :)
I did notice 16 NULL bytes in the debugger near AES code. Should have guessed a Zero IV. Doh! :)
haha, at least this wasn't too hard to crack. the scryot settings are quite high. im not sure how cards will handle such high N values.
A kernel can now be written.
Yep!
To make bcve2john.py
robust, can we scan for those blowfish sbox values
to locate the BCVE header? Or is there a better way to do this?
A kernel can now be written.
Yep!
To make
bcve2john.py
robust, can we scan for thoseblowfish sbox values
to locate the BCVE header? Or is there a better way to do this?
I think that is the best way. maybe also checking the MBR/GPT for multiple partitions and following the disk offsets.
just confirmed that it is working and decrypting properly
If possible, let's not rely on MBR/GPT structures to find partitions. I wonder how slow a linear brute force for finding those Blowfish table values will be... probably too slow for bigger disks?
If possible, let's not rely on MBR/GPT structures to find partitions. I wonder how slow a linear brute force for finding those Blowfish table values will be... probably too slow for bigger disks?
True, if they are always block aligned, you would only need to check the first say 4 bytes of each 512 block. might be faster then
i have noticed that the first 16 bytes of the blowfish table appears a lot of times
BCVE must be writing backups of its header? Are they same? Can any of them be used for cracking purposes?
no they are not the same. and there are hundreds on a 10mb disk
you can tell v3 and v4 partitions apart by presence of the secondary salt at 0x166:0x176
Hi guys,
i know that the Jetico bestcrypt container format is supported, but would it be possible to add the volume encryption format. It doesnt seem to be supported by any other tools.
I have tried to find some source code to the format and not managed to, i have also done some work on the header but not got anywhere.
Thanks