libyal / libbde

Library and tools to access the BitLocker Drive Encryption (BDE) encrypted volumes
GNU Lesser General Public License v3.0
214 stars 52 forks source link

unable to open partially encrypted volume with pybde? #54

Closed arothenhaeuser closed 2 years ago

arothenhaeuser commented 2 years ago

I tried to open an image of a hard drive, which I believe to be half-way encrypted, using python. Unfortunately pybde refuses to open it.

import pybde
print(pybde.get_version())
# 20200724

try:
    bde_volume = pybde.volume()
    bde_volume.open("/mnt/e/image.raw")
    bde_volume.close()
except Exception as e:
    print(e)
# pybde_volume_open: unable to open volume. libbde_io_handle_read_volume_header: unsupported volume boot entry point. libbde_volume_open_read: unable to read volume header. libbde_volume_open_file_io_handle: unable to read from file IO handle. libbde_volume_open: unable to open volume: /mnt/e/image.raw.

try:
    file_object = open("/mnt/e/image.raw", "rb")
    bde_volume = pybde.volume()
    bde_volume.open_file_object(file_object)
    bde_volume.close()
except Exception as e:
    print(e)
# pybde_volume_open_file_object: unable to open volume. libbde_io_handle_read_volume_header: unsupported volume boot entry point. libbde_volume_open_read: unable to read volume header. libbde_volume_open_file_io_handle: unable to read from file IO handle.

I manually verified, that there is an intact bitlocker volume header starting at offset 1048576 (dec):

eb 58 90 2d 46 56 45 2d 46 53 2d 00 10 40 20 00 00 00 00 00 00 f8 00 00 3f 00 ff 00 3f 00 00 00 20 09 aa 2b e0 1f 00 00 00 00 00 00 00 00 00 00 01 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 29 00 00 00 00 4e 4f 20 4e 41 4d 45 20 20 20 20 46 41 54 33 32 20 20 20 33 c9 8e d1 bc f4 7b 8e c1 8e d9 bd 00 7c a0 fb 7d b4 7d 8b f0 ac 98 40 74 0c 48 74 0e b4 0e bb 07 00 cd 10 eb ef a0 fd 7d eb e6 cd 16 cd 19 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3b 4d a8 92 80 dd 0e 4d 9e 4e b1 e3 28 4e ae d8 00 20 7f 53 08 00 00 00 00 20 87 53 08 00 00 00 00 20 8b 53 08 00 00 00 00 20 9f 53 08 00 00 00 00 20 a3 53 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0d 0a 52 65 6d 6f 76 65 20 64 69 73 6b 73 20 6f 72 20 6f 74 68 65 72 20 6d 65 64 69 61 2e ff 0d 0a 44 69 73 6b 20 65 72 72 6f 72 ff 0d 0a 50 72 65 73 73 20 61 6e 79 20 6b 65 79 20 74 6f 20 72 65 73 74 61 72 74 0d 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 1f 2c 55 aa

Is there anything I can do to further narrow down the problem? Or is this simply not supported by the library?

joachimmetz commented 2 years ago

If you can provide a test image or debug output (see: https://github.com/libyal/libbde/wiki/Troubleshooting#format-or-behavioral-errors) that could help narrow down the issue.

Though based on your Python code it looks like you're reading the start of the image not the start of the volume.

arothenhaeuser commented 2 years ago
$ fdisk -l image.raw
Disk /mnt/e/image.raw: 2.75 TiB, 3000592982016 bytes, 5860533168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x9a69dc6b

Device              Boot Start       End   Sectors   Size Id Type
/mnt/e/image.raw1        256 732563999 732563744 349.3G  c W95 FAT32 (LBA)

fdisk implies an offset of 256 * 512 = 131072, whereas manual search for "ëX.-FVE-FS-" implies an offset of 1048576. I tried pointing pybde to both positions, but receive the very same error message:

try:
    file_object = open("/mnt/e/image.raw", "rb")
    file_object.seek(131072)
    bde_volume = pybde.volume()
    bde_volume.open_file_object(file_object)
    bde_volume.close()
except Exception as e:
    print(e)
# pybde_volume_open_file_object: unable to open volume. libbde_io_handle_read_volume_header: unsupported volume boot entry point. libbde_volume_open_read: unable to read volume header. libbde_volume_open_file_io_handle: unable to read from file IO handle.
try:
    file_object = open("/mnt/e/image.raw", "rb")
    file_object.seek(1048576)
    bde_volume = pybde.volume()
    bde_volume.open_file_object(file_object)
    bde_volume.close()
except Exception as e:
    print(e)
# pybde_volume_open_file_object: unable to open volume. libbde_io_handle_read_volume_header: unsupported volume boot entry point. libbde_volume_open_read: unable to read volume header. libbde_volume_open_file_io_handle: unable to read from file IO handle.

Unfortunately I can't provide the image itself, nor was I able to produce the debug output you requested (I used setup.py to build your project). Any further help is much appreciated!

joachimmetz commented 2 years ago

Your file_object should have the BDE volume at offset 0 (not the start of the image)

Have a look at the DataRangeFileObject in https://gist.github.com/joachimmetz/58962c679370518d54065f0f4dad685a#file-vshadow-store-read-py-L33

arothenhaeuser commented 2 years ago

Okay, so after some modifications of the code you linked I can do this:

try:
    drfo = DataRangeFileObject(1048576, 375072767488)
    drfo.open("/mnt/e/image.raw")
    print(binascii.hexlify(drfo.read(16), " "))
# b'eb 58 90 2d 46 56 45 2d 46 53 2d 00 10 40 20 00'
    drfo.seek(0)
    bde_volume = pybde.volume()
    bde_volume.open_file_object(drfo)
    bde_volume.close()
except Exception as e:
    print(e)
# pybde_volume_open_file_object: unable to open volume. libbde_io_handle_read_volume_header: unsupported identifier. libbde_volume_open_read: unable to read volume header. libbde_volume_open_file_io_handle: unable to read from file IO handle.

I think my DataRangeFileObject now has the BDE volume at offset 0, but still I get the same error. What am I doing wrong this time? Please don't tell me its simply a corrupted disk image ;)

joachimmetz commented 2 years ago

but still I get the same error.

No you're not. You now get libbde_io_handle_read_volume_header: unsupported identifier. versus libbde_io_handle_read_volume_header: unsupported volume boot entry point.

joachimmetz commented 2 years ago

This indicates an unsupported version of a BDE volume. Could this be related to https://github.com/libyal/libbde/issues/39 ? See the troubleshooting link I sent earlier to get more information about the data format.

arothenhaeuser commented 2 years ago

I sent you some debug output via pm. I believe that used disk space only encryption was used, thus it was not working without debug mode.

joachimmetz commented 2 years ago

Per out of band conversation this is a duplicate of https://github.com/libyal/libbde/issues/39