AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 741404
Accepted
sataoverflow
sataoverflow
Asked: 2023-03-30 11:50:54 +0800 CST2023-03-30 11:50:54 +0800 CST 2023-03-30 11:50:54 +0800 CST

用分区表覆盖 LUKS

  • 772

我现在知道这是一个愚蠢的决定,我尝试使用 windows 安装程序双启动 Windows 和 linux,在启动到 windows 安装程序后,我选择了 2 个大小约为 500GB 的克隆硬盘驱动器中的一个来擦除,因为它们是clone 如果我选择一个而不是另一个也没关系。

这样做之后,安装程序说它更改了其中一个 500GB 硬盘的分区表,然后无法安装 Windows。在没有复制文件的情况下因错误而崩溃,或者它说,当它说它甚至无法开始安装时,我不确定我是否可以信任它。

所以我启动到我的 linux 安装以检查它覆盖了哪个驱动器并手动安装它。相反,迎接我的是我的其他驱动器之一,一个 6TB dm-luks 和 btrfs 驱动器,丢失了。不仅两个 500GB 驱动器都没有动过,而且 6TB 驱动器似乎添加了一堆乱七八糟的分区。6个分区依次为499M、99M、499M、100M、499M、100M。

由于我的驱动器很大而且很慢,运行到目前为止hexdump -C /dev/sda |grep LUKS产生了这么多,我会在完成时更新:

8d411ce0  e1 ad 4c 55 4b 53 c0 85  22 3d de 49 dd 44 fd 08  |..LUKS.."=.I.D..|
e6449610  d5 cf 4a 86 9f cc 4c 55  4b 53 a9 a9 16 cc ba 1d  |..J...LUKS......|
446ea9a70  b3 db a9 bf 8b 2e 41 4c  55 4b 53 ef f0 75 b0 18  |......ALUKS..u..|
4732c6040  e0 b3 bb ff 4c 55 4b 53  4c c2 5b 12 c6 41 fc d6  |....LUKSL.[..A..|

到目前为止,自从发生这种情况以来,唯一接触过磁盘的是 hexdump,我对运行 testdisk 犹豫不决,因为我听说它会覆盖驱动器上的数据,并且它不会将 luks 列为它可以搜索的内容。

我可以看到其他人使用 hexdump 来检查完整的标头,但是,我不知道我到底在寻找什么。

此时我能做些什么来查看是否可以恢复标头的任何位。有没有办法运行 testdisk 或其他工具来查找 luks 标头以判断它们是否已被覆盖?任何让我知道是否一切都是 FUBAR 的方式都与恢复我的数据的方式一样受欢迎。

编辑

在没有 grep 的情况下在驱动器的第一位上运行 hexdump 显示至少有一些完整的 JSON,从到00005000显示00005310同样多,我更不确定我现在特别寻找的是什么以了解它是否仍然完好无损。它似乎覆盖了数据直到这个确切的字符串。

00005000  7b 22 6b 65 79 73 6c 6f  74 73 22 3a 7b 22 30 22  |{"keyslots":{"0"|
00005010  3a 7b 22 74 79 70 65 22  3a 22 6c 75 6b 73 32 22  |:{"type":"luks2"|

删除中间的数据,因为它包含盐,但块结束于:

000052f0  22 2c 22 6b 65 79 73 6c  6f 74 73 5f 73 69 7a 65  |","keyslots_size|
00005300  22 3a 22 31 36 37 34 34  34 34 38 22 7d 7d 00 00  |":"16744448"}}..|
00005310  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*

它完好无损吗?

data-recovery
  • 1 1 个回答
  • 114 Views

1 个回答

  • Voted
  1. Best Answer
    frostschutz
    2023-04-04T08:09:26+08:002023-04-04T08:09:26+08:00

    cryptsetup repair, 第二部分 — 完整标头恢复

    • 另请参阅:cryptsetup repair,第 1 部分 - 魔术字节恢复

    为了恢复部分覆盖的 LUKS2 标头,您至少需要两件事:第一,至少一个密钥槽的密钥材料。第二,描述如何使用密钥材料的元数据(算法、迭代计数、盐等)。

    密钥材料是大约 256KB 的随机数据,通常位于偏移量 32768 (0x8000) 及以后,但是必须根据元数据确定确切的偏移量和大小。

    元数据是一个 JSON 字符串,通常位于偏移量 4096 (0x1000) 和 20480 (0x5000) 处。LUKS2 维护它的两个相同副本(主要和次要标头)。密钥材料本身只存在一次。

    如果分区表本身也丢失了,您还必须确定正确的分区偏移量。


    设置:

    # truncate -s 128M disk.img
    # losetup --find --show --partscan disk.img
    /dev/loop0
    # parted /dev/loop0 -- mklabel gpt
    # parted /dev/loop0 -- mkpart luks $((RANDOM%100))MiB 100%
    # cryptsetup luksFormat --type luks2 /dev/loop0p1
    
    WARNING!
    ========
    This will overwrite data on /dev/loop0p1 irrevocably.
    
    Are you sure? (Type 'yes' in capital letters): YES
    Enter passphrase for /dev/loop0p1:
    Verify passphrase:
    # cryptsetup open /dev/loop0p1 luks
    Enter passphrase for /dev/loop0p1:
    # mkfs.ext2 -L encrypted /dev/mapper/luks
    # blkid /dev/mapper/luks
    /dev/mapper/luks: LABEL="encrypted" […] TYPE="ext2"
    

    一个闪亮的新加密文件系统!

    损害:

    # cryptsetup close luks
    # wipefs -a /dev/loop0p1
    /dev/loop0p1: 6 bytes were erased at offset 0x00000000 (crypto_LUKS): 4c 55 4b 53 ba be
    /dev/loop0p1: 6 bytes were erased at offset 0x00004000 (crypto_LUKS): 53 4b 55 4c ba be
    # dd count=32 if=/dev/urandom of=/dev/loop0p1
    32+0 records in
    32+0 records out
    16384 bytes (16 kB, 16 KiB) copied, 0.000334077 s, 49.0 MB/s
    # wipefs -a /dev/loop0
    /dev/loop0: 8 bytes were erased at offset 0x00000200 (gpt): 45 46 49 20 50 41 52 54
    /dev/loop0: 8 bytes were erased at offset 0x063ffe00 (gpt): 45 46 49 20 50 41 52 54
    /dev/loop0: 2 bytes were erased at offset 0x000001fe (PMBR): 55 aa
    /dev/loop0: calling ioctl to re-read partition table: Success
    # losetup -d /dev/loop0
    

    所以这是一个带有 LUKS2 分区的 disk.img,偏移量未知,上面有损坏的标头(魔法字节已擦除,部分覆盖,分区表已擦除)。


    元数据恢复:

    由于 LUKS2 JSON 字符串是纯 ASCII,因此可以使用 找到它strings,这也会显示偏移量:

    # strings -n 64 -t d disk.img | grep -P '"[a-z]+":'
    60837888 {"keyslots":{"0":{"type":"luks2","key_size":64,"af":{"type":"luks1","stripes":4000,"hash":"sha256"},"area":{"type":"raw","offset":"32768","size":"258048","encryption":"aes-xts-plain64","key_size":64},"kdf":{"type":"argon2id","time":13,"memory":1048576,"cpus":4,"salt":"R1z3arzSCjRb3STaCAnstIygkHCXf0CHf6kXl5yQj/E="}}},"tokens":{},"segments":{"0":{"type":"crypt","offset":"16777216","size":"dynamic","iv_tweak":"0","encryption":"aes-xts-plain64","sector_size":512}},"digests":{"0":{"type":"pbkdf2","keyslots":["0"],"segments":["0"],"hash":"sha256","iterations":324435,"salt":"0nSkpvmDJlvfkDaQteVVo6JdD/Oqt3vnndkZt1Qnd84=","digest":"lefQ21EaiuSdHFhSIFW3wDfMcRqG0HLCAO1bGI3SfvM="}},"config":{"json_size":"12288","keyslots_size":"16744448"}}
    

    所以这里我们在偏移量 60837888 处有一个完整的 JSON 字符串。将其复制并粘贴到header.json文件中。该文件应以 开头{和结尾}。您可以使用它jq来确保它确实是一个有效的 JSON 字符串,并以更易于阅读的形式显示它:

    # jq < header.json
    {
      "keyslots": {
        "0": {
          "type": "luks2",
    […]
      }
    }
    

    分区恢复:

    LUKS2 标头中 JSON 元数据的偏移量通常为 4096 或 20480,具体取决于它是主标头还是辅助标头。您必须从strings之前找到的偏移量中减去这些值。

    因此,在这种情况下正确的分区偏移量可以是60837888 - 4096 = 60833792 = 58.02MiB或60837888 - 20480 = 60817408 = 58 MiB。由于后者是 MiB 对齐的,因此它更有可能成为正确分区偏移的候选者。

    如有疑问,请尝试两者。


    关键材料回收:

    根据 JSON 元数据,此 LUKS2 标头具有单个密钥槽,其密钥材料位于"offset":"32768","size":"258048". 让我们抓住它dd:

    # partition=60817408
    # offset=32768
    # size=258048
    # dd bs=1 skip=$((partition+offset)) count=$((size)) if=disk.img of=header.$((offset))
    

    如果有多个键槽,请对每个键槽重复此过程。

    密钥材料应该看起来像随机数据。要验证这一点,您可以使用hexdump -C.

    # hexdump -C header.32768
    00000000  f1 3b 23 73 98 d7 8f e3  22 24 9a 9d 5a 2c a9 ae  |.;#s...."$..Z,..|
    00000010  95 82 3e c6 df e7 0e a0  f4 ba 54 6c 7f e9 fa f6  |..>.......Tl....|
    00000020  b7 12 64 8d 7d a5 ca 4b  c8 89 89 08 3e de 59 0d  |..d.}..K....>.Y.|
    […]
    0003efe0  b2 b3 bc cd de 60 17 a7  57 bb 1a 84 5a 15 68 95  |.....`..W...Z.h.|
    0003eff0  7f 1f 07 ee ee d1 e8 a2  6c cf 5f 40 0b 73 00 0b  |[email protected]..|
    0003f000
    

    或者您可以尝试压缩它并查看压缩结果是否更小:

    # gzip < header.32768 > header.32768.gz
    # stat -c %s area.*
    258048
    258106
    

    随机数据通常根本无法压缩,所以如果 gzipped 版本没有变小(甚至大几个字节),那么整个数据很可能是随机数据。

    真正的验证只有在最后才有可能——当它接受或不接受你的密码时。


    完整标头恢复:

    在你收集了上面的必要成分后,你可以尝试从中重建一个完整的标题:

    # truncate -s 16M luks.recovery
    # cryptsetup luksFormat --type luks2 luks.recovery
    # cryptsetup luksErase luks.recovery
    

    使用 cryptsetup 生成一个有效但不可用的没有密钥槽的标头。这里的目的是获取一个文件,该文件设置了所有正确的魔术字节、UUID 等——与加密无关,但它是使 LUKS 标头成为 LUKS 标头的原因。

    现在将您的元数据移植到它上面:

    # printf "%s\0" "$(jq -c < header.json)" |
        dd conv=notrunc bs=1 seek=4096 of=luks.recovery
    # printf "%s\0" "$(jq -c < header.json)" |
        dd conv=notrunc bs=1 seek=20480 of=luks.recovery
    

    以及关键材料:

    # dd conv=notrunc bs=1 seek=32768 if=header.32768 of=luks.recovery
    

    在这一点上,我们终于完成了,除了:

    # cryptsetup luksDump luks.recovery
    Device luks.recovery is not a valid LUKS device.
    # cryptsetup repair luks.recovery
    Device luks.recovery is not a valid LUKS device.
    

    校验和恢复:

    咦,现在怎么了?添加--debug以了解:

    # cryptsetup luksDump --debug luks.recovery
    […]
    # LUKS2 header version 2 of size 16384 bytes, checksum sha256.
    # Checksum:5babf58f0f788911897989ff3d9a580de1c22db8869b3b08cd0d6d56906005cb (on-disk)
    # Checksum:b2ff5dd7b53978723402103ba914ed87ef2c5b5d9a9062d68363e4df38aebf6f (in-memory)
    […]
    

    LUKS2 的主要和次要标头有一个校验和。由于我们在没有更新校验和的情况下修改了 JSON 元数据,因此这是不匹配的。值得庆幸的是,cryptsetup 显示了预期值,因此我们不必手动计算它。

    此校验和是二进制标头的一部分,因此您必须使用xxd -r -p它来将其转换为二进制:

    # echo 5babf58f0f788911897989ff3d9a580de1c22db8869b3b08cd0d6d56906005cb | xxd -r -p | hexdump -C
    00000000  5b ab f5 8f 0f 78 89 11  89 79 89 ff 3d 9a 58 0d  |[....x...y..=.X.|
    00000010  e1 c2 2d b8 86 9b 3b 08  cd 0d 6d 56 90 60 05 cb  |..-...;...mV.`..|
    00000020
    # echo b2ff5dd7b53978723402103ba914ed87ef2c5b5d9a9062d68363e4df38aebf6f | xxd -r -p | hexdump -C
    00000000  b2 ff 5d d7 b5 39 78 72  34 02 10 3b a9 14 ed 87  |..]..9xr4..;....|
    00000010  ef 2c 5b 5d 9a 90 62 d6  83 63 e4 df 38 ae bf 6f  |.,[]..b..c..8..o|
    00000020
    

    用正确的内存校验和替换错误的磁盘校验和:

    # hexdump -C luks.recovery | grep '5b ab f5 8f 0f 78 89 11'
    000001c0  5b ab f5 8f 0f 78 89 11  89 79 89 ff 3d 9a 58 0d  |[....x...y..=.X.|
    # echo b2ff5dd7b53978723402103ba914ed87ef2c5b5d9a9062d68363e4df38aebf6f |
        xxd -r -p |
        dd conv=notrunc bs=1 seek=$((0x000001c0)) of=luks.recovery
    

    这应该能让事情继续进行。

    # cryptsetup repair luks.recovery
    # cryptsetup luksDump luks.recovery
    LUKS header information
    Version:        2
    […]
    

    总结一下:

    # losetup --find --show --read-only --offset 60817408 disk.img
    /dev/loop0
    
    # cryptsetup open --read-only --header luks.recovery /dev/loop0 luksrecovery
    Enter passphrase for /dev/loop0:
    
    # blkid /dev/mapper/luksrecovery
    /dev/mapper/luksrecovery: LABEL="encrypted" […] TYPE="ext2"
    

    完毕。最后。

    • 2

相关问题

  • 将目录移动到不存在的位置?

  • MDADM - 灾难恢复或从我将 RAID5 阵列放入的状态继续前进

  • 如何从 2 磁盘 NAS 中曾经属于 RAID1(MD 上的 LVM)的磁盘恢复/复制数据?

  • 用于移动使用 fdupes 或其他重复数据删除包删除的保留文件的脚本

  • dd_rescue 和 ddrescue 有什么区别,什么时候更喜欢哪一个?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve