Those who bear true belief in flxg shall fear no malbolge!
-- La Divina FLXG Commedia
FLXG 创始人 CWK 修为通玄, 万古罕有. 至今无敢直呼其名者, 皆以西文缩写代之.
据 神 FLXG 曲 载, CWK 为探 FLXG 之密, 曾 排空驭气奔如电, 升天入地求之遍. 上穷碧落下尽黄泉, 两处茫茫而无可见. 后其闭关九年, 又仗三尺长剑, 携一刀生宣, 闯 但丁 旧时幽路. 平荆棘, 暴霜露, 惊恶魑, 斩狱卒, 神鬼莫可当之.
每其行足七千里也, 元气化墨, 即为箧囊所藏, 凝之一字, 现诸纸上. 及至伊甸园, 经义已成十万八千字余矣. 当是时, 人间科技正高速发展, 上帝不得已, 将 2D 天空贴纸更为 3D, 故而旧道不通. CWK 举目四望, 但见群星闪烁. 扪参历井, 方知穷途将归.
归来后, 宣纸已自编纂成册, 即 神 FLXG 曲 (曾藏于滑稽大学博物院, 现已佚失). 其中记载 CWK 种种经历此处且按下不提. 而 Inferno: Malebolge 一章, 以 Malbolge 语言书成. 虽晦涩难通, 所谓佶屈而聱牙, 然真义无穷, 实乃无上之道法.
江湖余此残篇, 而今公示于天下. 可否有所体悟, 且看诸君之造化.
质因数分解,添加换行符,缩小字体
Malbolge 语言是会忽略空格的,可是为什么 txt 里面有这么多空格呢?
用文本编辑器打开发现,这些字符好像有些规律。调小字体大小后发现有明显的 pattern。
用浏览器打开(firefox 和 chrome 都行,黑曜石也行),调到合适的字体大小,再手动调整宽度,可以看到一个畸变的图案,不过不影响做题,仍然可以读出 flxg。很多人提交记录里面把大写 U 看成小写,估计都是用这种方法做的。
当然官方解法肯定不是这么做的。
使用 wc 命令统计一下字符数,发现一共有 154012 个字节。我们应该可以猜到这个文件是个字符画,但是换行被去掉了所以变得很难看。使用 factor 或者 yafu 对这个数进行质因数分解,发现 154012 = 2 * 2 * 139 * 277。经验上,等宽字体字符画像素上的长宽比和字符数的长宽比大致在 1 : 2 左右。所以我们猜测,这个字符画的长宽大概是 556 * 277 或者 574 * 278。
使用 python 或其他语言,每隔这么多字符打印一次 '\n',在控制台上能看到非常正宗的滑稽图案。flxg 赫然醒目。
https://www.matthias-ernst.eu/malbolgereverse.html
其实这道题主要考察选手 Google 能力..。
从出题人的角度,如果要出一道 Malbolge 逆向,出题人会怎么写代码。
其实这道题的关键就在于弄清楚条件判断是如何实现的。Malbolge 语言没有条件跳转语句,所以只能通过跳转表模拟。弄清楚这一点的话剩下的就是时间问题了。
所以通过搜索,能找到 Cat halts on EOF 这个程序的源码。甚至可以找到 https://github.com/zb3/malbolge-tools/blob/master/samples/src/q.hell 。
通过 HELL IDE 反汇编,可以看到这份代码与本题之间的相似程度非常之高。实际上,许多 Malbolge 程序处理 if 判断的方法基本都是同一份代码。
确定本题是由 HELL IDE 编译的又一方法是观察代码的前几个字节。HELL IDE 在编译的时候会增加一些初始化的代码,相当于给内存分成代码区和数据区。仔细与其他程序比较可以看到明显的共同点。
另一种预期做法,污点分析。
可以注意到键盘的输入会相互 ROT 和 CRZ,最终形成一个 Ternary byte,之后的处理就全部基于这个字节上进行,输入数据的其他信息都丢失。所以可以对这个字节进行爆破,自己写好调试器之后十分简单。
(此处省略爆破代码)
做出来题目的同学并不期望能拿到 Key,因为这是一个多对一的压缩过程。这里给一个可行的 Key: ./;'[]-=0 本题 HELL 源代码见 flxg.hell 文件。