这是一个快速的 python 脚本,它将输出给定 LUKS 容器的开始和结束字节:
#!/usr/bin/python
################################################################################
# File: luksHeaderBounds.py
# Purpose: Determine the start and end bytes of a LUKS header
# Authors: Michael Altfield <michael@michaelaltfield.net>
# Created: 2020-03-18
# Updated: 2020-03-18
# Version: 0.1
################################################################################
# DEPENDS
import sys, struct, json;
# MAIN BODY
if len(sys.argv) != 2:
print "Usage: luksHeaderBounds.py <device>"
exit(1)
device = sys.argv[1]
# first we get the LUKS version
with open(device, "rb") as f:
# the LUKS version field is a big endian unsigned short (uint16_t = '>H')
# * https://docs.python.org/2/library/struct.html
# the LUKS version field starts at offset 6 bytes and is 2 bytes long
# so we get the first 8 bytes and the last 2 bytes of that
# * https://gitlab.com/cryptsetup/LUKS2-docs/blob/master/luks2_doc_wip.pdf
luksVersion = struct.unpack( '>H', f.read(8)[-2:] )[0];
if luksVersion == 1:
# LUKS1 - https://gitlab.com/cryptsetup/cryptsetup/-/wikis/LUKS-standard/on-disk-format.pdf
with open(device, "rb") as f:
# the payload-offset field is a big endian unsigned long (uint32_t = '>L')
# * https://docs.python.org/2/library/struct.html
# in LUKS1, the payload-offset field starts at offset 104 bytes and is 4 bytes long
# so we get the first 108 bytes and the last 4 bytes of that
# * https://gitlab.com/cryptsetup/cryptsetup/-/wikis/LUKS-standard/on-disk-format.pdf
payloadOffset = struct.unpack( '>L', f.read(108)[-4:] )[0];
# the payload-offset is just the number of (512-byte sized) sectors
# to get bytes we must multiply it by 512
luksHeaderEnd = 512 * payloadOffset
elif luksVersion == 2:
# LUKS2 - https://gitlab.com/cryptsetup/LUKS2-docs/blob/master/luks2_doc_wip.pdf
# first we get the header size from the primary binary header
with open(device, "rb") as f:
# the hdr_size field is a big endian unsigned long long (uint64_t = '>Q')
# * https://docs.python.org/2/library/struct.html
# in LUKS2, the hdr_size field starts at offset 8 bytes and is 8 bytes long
# so we get the first 16 bytes and the last 8 bytes of that
# * https://gitlab.com/cryptsetup/LUKS2-docs/blob/master/luks2_doc_wip.pdf
hdr_size=struct.unpack( '>Q', f.read(16)[-8:] )[0];
# the JSON plaintext metadata object starts after the header (4096 bytes)
# and ends at (hdr_size - 4096)
jsonSize = hdr_size - 4096;
with open(device, "rb") as f:
luksMetadata = f.read(hdr_size)[-jsonSize:];
decoder = json.JSONDecoder()
jsonMetadata = decoder.raw_decode(luksMetadata)
# the LUKS2 header ends at the start of the first data segment
luksHeaderEnd=jsonMetadata[0]['segments']['0']['offset']
else:
print "ERROR: Unable to determine LUKS version"
exit(1)
print "Device: " +str(device)
print " LUKS Header Start Byte: " +str(0)
print " LUKS Header End Byte: " +str(luksHeaderEnd)
exit(0)
以及 LUKS1 卷的示例执行:
root@disp4117:~# ./luksHeaderBounds.py luksVol1
Device: luksVol1
LUKS Header Start Byte: 0
LUKS Header End Byte: 2097152
root@disp4117:~#
以及 LUKS2 卷的示例执行:
root@disp4117:~# ./luksHeaderBounds.py luksVol2
Device: luksVol2
LUKS Header Start Byte: 0
LUKS Header End Byte: 16777216
root@disp4117:~#