Skip to content

Latest commit

 

History

History
142 lines (101 loc) · 6.7 KB

File metadata and controls

142 lines (101 loc) · 6.7 KB

室友的加密硬盘

先说出题人的预期解

文件根据说明是磁盘镜像,用 fdisk 查看基本情况,就假设文件叫 target 了:

$ fdisk -l target.img
Disk target.img: 1.91 GiB, 2048000000 bytes, 4000000 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: 0xa4ee910b

Device      Boot   Start      End  Sectors  Size Id Type
target.img1 *       2048   391167   389120  190M 83 Linux
target.img2       393214 16775167 16381954  7.8G  5 Extended
target.img5       393216  1890303  1497088  731M 82 Linux swap / Solaris
target.img6      1892352  3891199  1998848  976M 83 Linux
target.img7      3893248 16775167 12881920  6.1G 83 Linux

确实是磁盘, MBR 分区表,一个主分区,和一些 Linux 扩展分区 。明显文件只有 2GB ,最后一个分区只截取了一点点。

用 dd 提取出单独的分区来:

$ dd if=target.img of=boot.img bs=512 count=389120 skip=2048
$ dd if=target.img of=swap.img bs=512 count=1497088 skip=393216
$ dd if=target.img of=chome.img bs=512 count=1998848 skip=1892352

用 file 查看一下并尝试 mount ,看出主分区是 ext4 格式的 boot 分区; 976M 分区 LUKS 加密,应该是题目中描述的家目录所在分区; swap 内有 SWSUSP1 镜像,表示有休眠存在;最后一个 6.1GB 分区应该只能是根分区了。因为虽然磁盘只得到了一小部分,分区表仍然完整并会显示出所有的分区。

那么之后自然的思路是看看 boot 内有没有东西,毕竟有些不太注意安全的人是会图方便把 LUKS 的key 放在 boot 中以便开机不用输入密码的。于是:

$ sudo mount boot.img /mnt
$ cat /mnt/keyfile
I'm not that stupid to put plaintext key in /boot!

信不信由你,我是信了。

那怎么办呢? AES 又不能爆破,那就只有 swap 和根分区有戏了。

根分区只有一点点,但也可以通过 testdisk 之类看看内容,或者 strings 一下... 要是有更多的非预期解那也算是 OK 的。

那就看 swap 吧,既然休眠,那估计整个内存 dump 都在里头了,那就找一下 AES key 吧 -- 这一步萌新出题人不太清楚做题的人能不能想到,出题灵感来源于 cold boot attack ,本想弄一个真实冷启动 dump 出的内存镜像,但鉴于能力和成本不够,就索性用休眠导致的 memory dump 了。

搜索在内存镜像中找 AES key 的方法,我找到了以下几个:

  • findaes ,可用;

  • r2 ,可用,似乎更好;

  • aeskeyfind ,需要指定参数阈值,但也可以得到结果。

以 r2 为例:

$ r2 swap_orig.img
 -- I endians swap.
[0x00000000]> /ca
Searching 1 byte in [0x0-0x2db00000]
hits: 12
0x006529d8 hit0_0 d913145b01b203ca068e48d2f40b048639d8c6f4cfe93b22c3795945ca9d9e2a
0x00652b08 hit0_1 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
0x0737c9d8 hit0_2 37d7deb43c0223b8656dd6a862562a1a8360926278dc65f445eda2146844589f
0x0737cb08 hit0_3 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
0x0a18ca1a hit0_4 e4d58f63d629f38803da3c712c5a0cc2be774b9d925d136024a181315d91ac99
0x0a18cc0e hit0_5 136ce9ce0d3f130ebe629570a08bc2ea883e451533875140027d1b3fdb5d0091
0x0a32db50 hit0_6 31c69dff83847a6c3c3c091e4ff6113ca5799e1b63656f0bd51bd6490c20769c
0x0b1c873a hit0_7 fa01a98089a38f606c148694e7a3509aaccfc165068ed67f5715384b93e56aa6
0x0b1c890d hit0_8 e4581675c3f947f7b537a3dd6098e4a5898b0a18c2b3b0f675c61de4106fc6a1
0x0bd08b20 hit0_9 4c82f3493f9a3381f51c394ab8532bd037db64b793057aade3d6bf67cbebf933
0x0d013349 hit0_10 fa01a98089a38f606c148694e7a3509aaccfc165068ed67f5715384b93e56aa6
0x0d01351c hit0_11 e4581675c3f947f7b537a3dd6098e4a5898b0a18c2b3b0f675c61de4106fc6a1
[0x00000000]> q

嗯,确实有不少的 key 。题目描述密钥是 512 位(这也是 LUKS 分区加密的默认密钥),于是找两个地址相连的 key ,合并起来,尝试作为 LUKS 的 master key 打开分区。注意相连要正反顺序都试一下(应该反向连接)!

这里直接以最终的成功结果为示例了,首先把 key 写入文件:

$ echo e4581675c3f947f7b537a3dd6098e4a5898b0a18c2b3b0f675c61de4106fc6a1fa01a98089a38f606c148694e7a3509aaccfc165068ed67f5715384b93e56aa6 | xxd -r -p > key.txt

然后尝试用这个 keyfile 给 LUKS 镜像添加一个密码:

$ cryptsetup luksAddKey chome.img --master-key-file key.txt
Enter new passphrase for key slot: ( 此处随便输一个密码,比如1 )
Verify passphrase:

成功,然后打开分区:

$ sudo cryptsetup luksOpen chome.img chome
Enter passphrase for chome.img: ( 此处输入刚才写的密码 )

挂载并得到 flag :

$ sudo mount /dev/mapper/chome /mnt
$ cat /mnt/petergu/flag.txt

这里不慎透露了出题人信息,抱歉考虑不周。

其实,出题和解题过程完全参考了这两篇文章:

https://blog.appsecco.com/breaking-full-disk-encryption-from-a-memory-dump-5a868c4fc81e?gi=f61ce0646b62
https://access.redhat.com/solutions/1543373

注意,第一篇文章中一个有问题的地方是 LUKS 分区的大小和物理分区大小不同(你可以自己创建一个 LUKS 分区实验一下,对于题目,二者差了 4096 字节),所以用里面类似于 echo "0 <size> crypt aes-xts-plain64 <key> 0 </dev/drive> 4096" | sudo dmsetup create luks-volume 的方法是不行的,并且具体的加密方式题目中也没有提到。而红帽文章中直接用 master key 添加 key slot 的方法不需要知道这些信息。但本人也不是专业人士,具体细节还要以正规渠道得到的信息为准。

如果你能够搜到这两篇文章,尤其是第一篇(其实还是比较容易搜到的),那应该可以解出这个题了。

本来还想把家目录也只截一半,然后解密之后用 testdisk 把 flag.txt 恢复出来,但好像这样也没有变得更难,就算了。

一个非预期解

不知是因为 LUKS 分区打开的时候本该如此,还是出题人操作不慎在分区创建的时候密码复制到了剪贴板上,密码本身明文在 swap 中出现了,所以 strings 一下然后逐个字符串尝试就可以求解。但感觉其实这样做出来也算是正常解法了。密码是什么留作练习。

其他可能方法

本题目的制作方法是在虚拟机装装上 xubuntu ,休眠之后 dump 出磁盘的一部分。就算不知道这个过程,一个自然的想法是尝试恢复启动,在 Linux 启动至 initrd 时进行分析(libreliu的思路)。我没有试过,也留作练习。