比赛情况

  • 比赛时间(UTC-8):2021-11-13 09:00:00 ~ 2021-11-15 09:00:00,共计 48 h
  • 比赛模式:解题模式(动态分值,无一血奖励)
  • 队伍总分:6016
  • 队伍排名:7
  • 贡献分数:0

前言与吐槽

第一次打正儿八经的 CTF,因为 Misc 方向没人做所以想去试试。

其实就是我啥都不会还想凑热闹而已

不过很遗憾,从各个队伍的解题情况来看,这次 Misc 除了签到题就没有什么能写的题目。

我只看了一道题目 BootFlag,从 13 号上午 10 点一直看到 14 号晚上睡觉。中途善良的 cwz 大爷前来支援,给了我巨大的精神激励。结果还是没写出来。长达 3 页半的 Google 文档生动形象地展示了我当时有多么发狂。

不过这道题难度确实不低,貌似到比赛结束为止,这道题也就只有 5 个队伍解出来。

(然而其他 Misc 更是重量级……)

当然,如果是那种一点希望都没有的 “做不出来”,那我就不会在这里写留档了对吧?实际上我们离完全解出题目已经不远了,思路基本上是对的,但是细节上出了一些问题。正因如此,我才想写下这篇留档,总结经验,吸取教训,争取下次还寄能写出一题。

未解出的题目

BootFlag

附件给了一个压缩包,拉下来解压缩之后发现里面装了一个视频和一个 bin 文件。bin 文件是 AMI Aptio UEFI 固件,视频是密码设置的全过程录屏。

题目要求是,提取 BIOS 中的 Administration Password 和 User Password。

从视频中可以看出,两个密码都只有四位,而且题目也给了密码的取值范围,很明显是想让我们爆破。

一开始我想的是,直接通过虚拟机一类的东西加载 BIOS 固件,然后想办法自动化爆破,然而缺乏经验的我连用虚拟机加载 BIOS 这一步都无法完成,只好作罢。

而且后来才想起来,密码还是有 1M+ 种情况的,这么爆破还是不现实。

那就只能求助谷歌娘了,Google 搜索 AMI BIOS Password Recovery,可以找到如下链接:https://gist.github.com/en4rab/550880c099b5194fbbf3039e3c8ab6fd

文章的作者使用了 UEFITool 这一工具,提取了固件中存储于 AMITSESetup 模块的密文,并使用异或解密成功恢复了明文。

然而,当我们满心欢喜地敲开 BIOS 的脑壳(在 follow 上述文章的步骤前,请注意你的 UEFITool 的版本,我在这里吃了亏),提取密文,试图用同样的方法获取明文时,却明显地发现了不对劲。

首先,我们提取出的密文长度与文章中的密文长度不一致。具体来说,在忽略掉末尾的 0 之后,我们提取出的密文长度为 256 bits,而文章中的密文长度却是 512 bits。

其次,对我们获取的密文尝试进行异或解密遭到了失败。这就说明,我们手中的密文使用了另外的加密方式。

在没有提示的情况下,我们也可以猜测其加密方式。256 bits 的密文长度很有代表性。更重要的是,题目的意思很明显是让我们爆破密码。综合上述两点,最有可能符合要求的加密方式就是 SHA-256 了。

然而,现在的问题在于,经过 cwz 大爷和我的尝试,直接对明文字符串用 Python 进行 SHA-256 的爆破是没有结果的。

我想到,会不会是对面的 SHA-256 加密方式有一些奇奇怪怪的变动,从而能够适应固件的需求呢?可如果真是这样,我们又如何知道他们到底是如何进行 SHA-256 的加密呢?

两个办法,一个办法是,用 UEFITool 把负责密码的模块 AMITSE 提取出来,交给 Reverse 大佬逆掉。这就是我为什么前面说后悔没去活动室找彪哥抱大腿的原因(虽然其实我当时也没想到把固件模块直接逆掉)

当然还有一个办法,不过要结合提示来看,自己想起来还是比较困难的。在我搜索 AMI BIOS Password Recovery 的过程中,我注意到,有一个网站提到,Aptio 的源代码曾经遭到过泄露,但当时我没有在意。

然而,提示出来之后,我在 Github 上乱逛的时候,意外发现了 Aptio 泄露的源代码,正好对应了提示信息中的 Github leak。

当时好像已经是 14 号下午了,我欣喜若狂,心说我这他妈不是稳了吗?!

然后我就在这里寄了。官方 WP 里一句轻描淡写的 “仔细阅读源码” 就给我干碎了。

我的爆破代码漏了两个东西。

一个是 UTF-16 的编码。这玩意是不兼容 ASCII 编码的,我当时还在想为啥 Password 要用 UINT16,而不是 UINT8 来存储。
一个是将明文的二进制表示用 0 补全到 40 字节。
考虑到这两个因素之后,官方的 WP 的爆破代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import hashlib
import itertools
import string

hash1 = ("c0470b97efc32108a06fe1b695b447c845f78d90438f43f1e2bed18a5af4e704")
hash2 = ("ab1e1a0f2127221775bc850312da0ba81e55a13e0c08f144382b6b11c8890494")

for i in itertools.permutations(string.digits+string.ascii_letters, 4):
p = ''.join(i)
p = str.encode(p, 'utf-16')[2:]
p = p.ljust(40, b'\x00')
hash = hashlib.sha256(p).hexdigest()

if hash == hash1:
print("hash1:", ''.join(i))

if hash == hash2:
print("hash2:", ''.join(i))

运行脚本即可获得两个密码,从而解出 flag。