Immutable source
No repair command ever targets the original encrypted VMDK.
Incident recovery field guide
A practical, safety-first runbook for operators and AI agents reconstructing partially encrypted VMware disks with read-only LVM mappings, surviving XFS metadata, and capped copy-on-write repair.
Important: this is usually filesystem reconstruction, not cryptographic decryption.
No repair command ever targets the original encrypted VMDK.
All modifications stay inside a measured, disposable COW layer.
Every sector offset, hash, mapping, and result is recorded.
This runbook describes a conservative method for recovering data from VMware ESXi VMDK files damaged by Babuk-style ransomware. It is intended for system administrators, incident responders, and AI agents operating under human supervision.
The method described here is usually reconstruction, not cryptographic decryption. It works when ransomware has encrypted only selected regions—often the beginning of a virtual disk—while later filesystem data and backup metadata remain intact.
There is no universal command that decrypts every .babyk file. A genuine decryptor requires the correct ransomware variant and cryptographic key. Never claim that reconstruction is decryption.
independent-nonpersistent mode.xfs_repair -n before any modifying XFS command.xfs_repair -L on the original disk or a direct read-only reconstruction./dev/sdX letters.Encrypted flat VMDK (immutable)
|
v
Clean VMDK descriptor excluding ransomware footer
|
v
VMware independent-nonpersistent disk
|
v
Linux read-only block device
|
v
Read-only LVM/LV device-mapper reconstruction
|
v
Disposable capped device-mapper COW snapshot
|
v
XFS repair inside COW only
|
v
Read-only recovered mount -> copy data elsewhereEvery layer above the disposable COW must remain read-only.
Before recovery:
Do not assume that an attacker is gone merely because encryption stopped.
Identify both parts of each virtual disk:
vm-name.vmdk.babyk
vm-name-flat.vmdk.babykThe small .vmdk is normally a text descriptor. If ransomware encrypted it, it may appear as binary data. The large -flat.vmdk contains the virtual disk sectors.
Collect read-only facts:
ls -l /vmfs/volumes/DATASTORE/VM/
stat /vmfs/volumes/DATASTORE/VM/vm-name-flat.vmdk.babyk
hexdump -C -n 128 /vmfs/volumes/DATASTORE/VM/vm-name-flat.vmdk.babyk
tail -c 128 /vmfs/volumes/DATASTORE/VM/vm-name-flat.vmdk.babyk | hexdump -C
vmkfstools -D /vmfs/volumes/DATASTORE/VM/vm-name-flat.vmdk.babykCheck for:
If analysis confirms a 64-byte footer:
tail -c 64 SOURCE-flat.vmdk.babyk > SAFE_LOCATION/SOURCE.babyk.footer64
chmod 400 SAFE_LOCATION/SOURCE.babyk.footer64
sha256sum SAFE_LOCATION/SOURCE.babyk.footer64Do not remove the footer from the original file.
If the encrypted flat file is the original disk plus a 64-byte footer:
real_bytes = encrypted_file_bytes - 64
sectors = real_bytes / 512Both divisions must be exact. Stop if the result is not sector-aligned.
Encrypted flat size: 5,497,558,138,944 bytes
Footer: 64 bytes
Real disk size: 5,497,558,138,880 bytes
Descriptor sectors: 10,737,418,240Create a new tiny descriptor; do not replace the encrypted descriptor.
# Disk DescriptorFile
version=1
encoding="UTF-8"
CID=fffffffd
parentCID=ffffffff
createType="vmfs"
# Extent description
RW 10737418240 VMFS "vm-name-flat.vmdk.babyk"
# The Disk Data Base
#DDB
ddb.adapterType = "lsilogic"
ddb.geometry.cylinders = "668373"
ddb.geometry.heads = "255"
ddb.geometry.sectors = "63"
ddb.virtualHWVersion = "14"The RW value is the important field. It must expose only the real disk sectors and exclude the ransomware footer.
Validate the descriptor without opening it in a VM:
vmkfstools -e /vmfs/volumes/DATASTORE/VM/vm-name-recovery.vmdkExpected result:
Disk chain is consistent.Never begin a full clone unless enough space exists for the actual allocation behavior of the operation.
For a 5 TiB source and only 2–3 TiB free, do not create a full clone. Use:
Thin provisioning does not eliminate the risk of datastore exhaustion.
Use a dedicated SystemRescue or forensic Linux VM. Power it off before changing VMX disk mode.
Add the recovery descriptor to a free SCSI slot, then ensure the VMX contains:
scsi0:3.mode = "independent-nonpersistent"Reload the VM configuration and verify the mode before powering on.
After Linux boots, identify the disk by its exact byte size and immediately set it read-only:
lsblk -b -o NAME,SIZE,TYPE,RO,FSTYPE,LABEL,MOUNTPOINTS
blockdev --setro /dev/sdX
blockdev --getro /dev/sdXThe last command must print 1.
Repeat this check after every reboot.
A .babyk extension alone does not prove file contents are encrypted. Check:
blkid -p /dev/sdX
wipefs -n /dev/sdX
fdisk -l /dev/sdX
parted -s /dev/sdX unit s print
dd if=/dev/sdX bs=64 count=1 status=none | od -An -tx1Interpretation:
If the affected data disk used LVM, look for backups on a recovered system/root filesystem:
/etc/lvm/backup/
/etc/lvm/archive/An LVM backup can preserve:
Important units: LVM text metadata normally records extent_size, pe_start, and dev_size in 512-byte sectors.
For a linear LV:
lv_length_sectors = extent_count * extent_size
lv_start_sector = pe_start + (start_extent * extent_size)extent_size = 8192 sectors # 4 MiB
pe_start = 2048 sectors # 1 MiB
start_extent = 0
extent_count = 1,310,719
lv_length = 1,310,719 * 8,192
= 10,737,410,048 sectors
lv_start = 2,048 sectorsCreate a read-only linear reconstruction:
dmsetup create vg_data-lv_data-recovery --readonly --table \
"0 10737410048 linear /dev/sdX 2048"
blockdev --getro /dev/mapper/vg_data-lv_data-recoveryThe read-only check must return 1.
Run only the no-modify check first:
xfs_repair -n /dev/mapper/vg_data-lv_data-recoveryA promising result looks like:
bad primary superblock
attempting to find secondary superblock
found candidate secondary superblock
verified secondary superblockThis proves that later XFS allocation-group metadata survives.
If the tool does not print the offset, trace read seeks without modifying data:
strace -f -e trace=lseek -o /tmp/xfs-repair.trace \
xfs_repair -n /dev/mapper/vg_data-lv_data-recoveryInspect large aligned seeks:
cat /tmp/xfs-repair.traceVerify candidate blocks directly. For a 4096-byte XFS block size:
dd if=/dev/mapper/vg_data-lv_data-recovery \
bs=4096 skip=CANDIDATE_BLOCK count=1 status=none |
dd bs=1 count=64 status=none | od -An -tx1A valid XFS superblock begins with hexadecimal:
58 46 53 42This is ASCII XFSB.
Do not repair the read-only reconstruction directly.
Load device-mapper snapshot support:
modprobe dm_snapshot
dmsetup targets | grep snapshotCreate a capped COW file on the recovery system disk. Ensure that filesystem has enough free space:
truncate -s 8G /persistent/data5tb-repair.cow
losetup --find --show /persistent/data5tb-repair.cowAssuming the returned loop device is /dev/loop2:
dmsetup create data5tb-repair --table \
"0 10737410048 snapshot /dev/mapper/vg_data-lv_data-recovery /dev/loop2 P 128"Verify all layers:
blockdev --getro /dev/sdX
blockdev --getro /dev/mapper/vg_data-lv_data-recovery
blockdev --getro /dev/mapper/data5tb-repair
dmsetup status data5tb-repair
du -h /persistent/data5tb-repair.cowExpected:
1).1).0).If the COW fills, the snapshot becomes invalid. Discard it and start again with a larger COW; the original remains unchanged.
First run without log destruction:
xfs_repair /dev/mapper/data5tb-repairIf XFS reports that the internal log contains metadata changes, first try a read-only mount with log replay disabled:
mkdir -p /mnt/data-recovery
mount -o ro,norecovery,nouuid /dev/mapper/data5tb-repair /mnt/data-recoveryIf the mount fails and the log cannot be replayed, -L may be necessary. Use it only on the disposable snapshot:
xfs_repair -L /dev/mapper/data5tb-repair-L destroys the XFS journal. It can lose the most recent uncommitted metadata changes. It is acceptable only after the original is protected and the repair target is disposable.
Monitor COW usage while repair runs:
dmsetup status data5tb-repair
du -h /persistent/data5tb-repair.cow
df -h /persistentAfter a successful repair:
mount -o ro,norecovery,nouuid \
/dev/mapper/data5tb-repair /mnt/data-recovery
findmnt /mnt/data-recovery
df -h /mnt/data-recovery
xfs_info /mnt/data-recoveryIf the original root directory inode was encrypted, XFS may reconnect surviving directory trees under:
/mnt/data-recovery/lost+found/Numeric names are normally inode numbers, not encrypted filenames. Child directory and file names can still be intact.
Classify recovered objects without reading all file contents:
find /mnt/data-recovery/lost+found \
-mindepth 1 -maxdepth 1 -printf '%y\n' | sort | uniq -cCreate a size index:
du -x -B1 --max-depth=1 /mnt/data-recovery/lost+found |
sort -nr > /persistent/recovered-top-level-bytes.txtThis can take time on filesystems with millions of inodes.
Copy from the read-only recovery mount to separate storage. Do not copy back to the affected datastore unless capacity is verified.
Example pull from a trusted destination:
rsync -aHAX --numeric-ids --info=progress2 \
root@RECOVERY_HOST:/mnt/data-recovery/lost+found/RECOVERED_TREE/ \
/safe/destination/RECOVERED_TREE/For untrusted or cross-organization destinations, use a dedicated restricted SSH account instead of root.
After copying:
Data blocks located inside the ransomware-encrypted region may remain corrupt even when their filenames and metadata are recoverable.
A live ISO normally loses network configuration, SSH keys, firewall rules, read-only flags, loop devices, and device-mapper mappings after reboot.
For long recoveries, install SystemRescue on a small dedicated virtual disk or configure its persistent backing store. Keep evidence disks separate. Use an autorun script to:
Official documentation:
Give the recovery agent an explicit contract similar to this:
You are assisting with ransomware recovery.
Treat every original VMDK and evidence file as immutable.
Do not mount original disks read-write.
Do not run repair tools without no-modify mode first.
Do not use xfs_repair -L except on a verified disposable COW target.
Before every modifying command, report:
1. the exact target,
2. whether it is original, clone, or COW,
3. the read-only state of every lower layer,
4. maximum additional storage consumption,
5. rollback procedure.
Identify disks by exact byte size and recorded UUIDs, not only /dev/sdX.
Keep a command log and verify every calculated sector offset.
Never expose passwords, private keys, customer filenames, or recovered data.
Stop if device identity, units, free space, or write isolation is uncertain.Agents should report recovery status using a consistent structure:
Original source: unchanged / read-only
VMware mode: independent-nonpersistent
Descriptor size: N sectors
LVM reconstruction: table and offsets verified
Filesystem: XFS UUID and geometry
Repair target: disposable COW only
COW used/capacity: X GiB / Y GiB
Repair phase/result: phase N / exit code
Recovered mount: path and mount options
Recovered allocated bytes: value
Unresolved risks: list
Next reversible action: command or procedurexfs_repair -L directly on the encrypted VMDK.norecovery; XFS may otherwise attempt log replay.A successful reconstruction has all of these properties:
ro,norecovery,nouuid.lost+found objects are accessible.Even after these conditions are met, rebuild production systems from clean installation media. Treat recovered data as untrusted input, not as a trustworthy operating system image.