「SECCONCTF2021」Rev | 汇编调试与马尔可夫图灵机
pyast64++.rev
题目实现了一个简单的 py 汇编器. 将可执行文件拖进 IDA 可以看到非常多成对的 push-pop 操作, 并且简单调试一下发现函数调用栈是一种奇怪的结构:
|
|
猜测出题人没有对编译出来的汇编代码做优化, 函数实现、传参以及用于栈保护的 canary 也是一种比较原始的实现. 大概有两种思路:
- 分析附件给出的 py, 写汇编器的恢复
- 直接逆二进制文件, 比较耗时但应该可做
比赛时选择了后者, 因为觉得是一种比较好上手的思路, 后面可以研究这个汇编器的实现, 看看能否恢复出抽象语法树.
程序流程大致如下:
|
|
比较套路化的过程, 主要是调试的时候由于赋值是通过 push-pop pairs, 比较耗时耗力. 然后由于栈结构的变化, 使得 IDA 的 F5 基本是不能细看, 推荐主要看汇编, 不太明白的地方 F5 参考一下. 代码恢复结果:
|
|
exp:
|
|
sed-programming
题目利用实现 sed 工具的核心算法 markov-algorithm 的图灵完备性, 实现了一门编程语言. 下面先来了解一下 markov-algorithm.
markov-algorithm
是一个字符串重写系统, 数学上被证明是图灵完备的, 意味着可以基于它实现通用计算模型、数学表达式、编程语言实现等. 它主要由两个部分组成: 可应用的字母表 + 映射方法集合 ${D=f(L) | L \rarr D}$, 其中 L 和 D 均表示由字母表中符号组成的任意的字符串, 我们假设 $\rarr$ 不存在于字母表中, 否则需要重新找一个分割字符串.
举个 🌰 方便理解:
alphabet = {|, *, a, b, c}
$$ f = \begin{cases} |b \rarr ba| \\ ab \rarr ba \\ b \rarr \\ \ast \rarr b \ast \\ - \rarr c \\ |c \rarr c \\ ac \rarr c| \\ c \rarr . \end{cases} $$
将该算法应用字母表中的任意字符串 V 的过程是一个离散的基本步骤序列. 我们假设 V′ 是在算法的前一步中得到的词 (或者是原始词 V,如果当前的步骤是第一步). 如果替换公式中没有包含在 V′ 中的左手边, 那么算法就终止了, 其工作结果被认为是字符串 V′. 否则, 将选择左手边包含在 V′ 中的 第一个 替换公式. 如果这个替换公式的形式是 L→D, 那么在 R L S 形式的字符串 V′ 的所有可能的表示中, 选择一个最短的 R, 之后字符串 R D S 被认为是当前步骤的结果, 需要在下一步骤中进一步处理.
比如上面的 🌰, |*|| 的结果是 ||, 可以自己验证一下.
sed
sed 功能强大, 支持正则匹配, 这道题用了三个:
s
ubstitutet
est. Jump if a substitution is donep
rint. Print the result after every substitution
我们可以先从后面单个字符的替换开始:
|
|
发现长度一致且为 8 的倍数, 猜测是 ascii code. 尝试定义映射集如下:
|
|
其实可以随便定, 然后就可以读一下变换出来的源码, 发现程序是基于 cursor 的一种变换:
- 生成 cursor,然后不停做类似 rol 的操作
- 每 3bit 分为一组,并替换成 count(‘1’) % 2 然后重复 0b1101 次
用 python 先把比较数提取出来, 思路是一个正则比较, 每次都从 bin(n) 去找 bin(n+1), 那么第二个 t 后面的一位就是待比较的数, 如下:
|
|
然后 exp 由于某些位已知, 思路类似:
|
|