首页
社区
课程
招聘
[原创][逆向不死]单指令CrackMe挑战:call是图灵完备的吗?
发表于: 14小时前 325

[原创][逆向不死]单指令CrackMe挑战:call是图灵完备的吗?

14小时前
325

引子
十一假期期间,打完第13届Flare-on,虽然拿到了Prize Token,但还是怅然若失。AI的滥用,让很多东西失去了意义。而且Google的逆向题更偏实战,格调上反而逊色于看雪。不过很遗憾,看雪杯赛程太长,实在是没有时间正经参与。
所以想着自己设计一道CrackMe,回应一下那些喊着“逆向已死”的朋友们,世界上很多事不是为了有用而去做的,甚至不是为了未来有用。

很多年以前,Stephen Dolan 发表过一篇论文:“mov是图灵完备的”。大致意思是,世界上只要有mov这一种指令,就能实现任何运算。后来git上有人在x86上完成了生产级实现(M/o/VFuscator),作为一种保护壳,可以把任意程序编译成只剩下mov指令。
图片描述
事实上,Dolan的论文和M/o/VFuscator项目,都没有真正意义上做到“单指令mov”。

延续这条思路,我做了一些无谓的探索和尝试,有了这道题最小PoC题:“call是图灵完备的吗?”。(见附件)
图片描述

图灵完备的书面定义是:“一个能够模拟任意图灵机的计算系统”。而图灵机本身能完成什么,又是一个大而抽象的概念。这种左脚踩右脚的定义方式,在计算机领域还挺常见,比如:“NP-hard问题,是指与NP问题中最难的那类一样难的问题”。这里我们不做过多纠缠。

一般情况下认为,具备以下三种能力的计算系统,就算图灵完备了:

而这里真正的问题是:

(本段跳过不影响文章理解)

抛开图灵完备来说,图灵机本身的定义,会具象很多。

图灵机可以表达为:

其中:

注:
我没有查到Q这个符号的辞源,猜测此处是借用了有理数集合的符号。
有理数是所有能转化为两个整数相除的数,那么符号Q大概率就来自于商的英语Quotient。

其中:

图片描述

在实现运算上,可以使用查表来代替运算。

比如要实现以下代码:

可以在内存中预存一张乘法口诀表:

当计算3*4时,直接从对应行列取数即可:

(注:这里便于理解,用mul[3][4]表示,实际语法遵循x86寻址表达式)

解决了运算的问题,接下来就是控制流

在不允许操作ip的情况下,影响控制流的方法,几乎完全等价于PWN的常用思路

M/o/Vfuscator项目的实现,选择了以下方式:

类似于一种CFF的编排,而非真正意义上的VMP。
图片描述

严格来说,这还是属于借助了外力。利用了设备自身的缺陷,数学洁癖上是难以接受的。

Dolan的论文中先否定了SMC形式。他认为这种方式可以往未来的text段中写入任意指令,属于作弊行为。
图片描述
比如:

实际上我觉也不尽然,如果我们只允许往未来的text段中写入mov指令,把命中当前逻辑分支的代码,搬运覆写到接下来要执行到的行。这种递归给自己铺路的方式,也有一定探讨价值。

类似这种操作:

图片描述

Dolan最终采用了VMP的方案,在text段使用mov作为解释器,把虚拟指令放在内存中。

不过可惜的是:他解释器的最后一行代码中必须保留一条jmp指令,真是纯学术流氓行为。
图片描述

有了前人的两个失败先例,我依然有冲动想去打造这台永动机。
虽然能隐约感觉到,单指令-完备-不借助外力,这个不可能三角难以兼得。

我们从图灵完备的定义出发,需要回答一个问题:是否存在一种指令,可以同时满足以下两点?

我枚举了下x86所有指令,筛选出一些满足条件的指令:

显然 call 是最特殊的。

在x86中,call是一条伪指令。为了创建新的调用栈帧,它会原子操作以下步骤:

一行 call 指令大致可以等价于:

这看起来简直就是为单指令图灵完备而生的 !!

另外,恰好PWN常用的ROP链相反,连续call会不停在stack中留下轨迹,同时影响栈顶指针。ROP能被广泛利用,同理call在我们的母题下也应该可以发挥作用。

有了一个朦胧的方向之后,就开始构思如何落地。
由于物理指令受限,能走的路几乎只有借用 VMP 的机制,做到更高语义上的功能拓展。

call的一个要命的问题在于,程序无法线性执行。当前行的call执行完之后,要被迫路由走,这导致预编排变得极为困难。

这里想到的机制,依然是沿用类似ROP链的思路:

内存结构大致是这样:
图片描述

这样还有个好处,就是 ESP+固定offset 未来必然踩到自己历史上 call 时 push 进去的地址。如此在虚拟指令层面,也能形成永久的循环

可以通过 ESP 的低位 SP 来控制奇偶循环触发的不同链路,达到逻辑分支的效果。

还是大 switch 形式,先在程序段中写好主体,每个handler中预留好 call $+5 占位。(单指令模式下,还是避免用NOP了)

图片描述

几番尝试后,实现了一个最小 PoC 的 CrackMe。当然,这个简陋的系统,距离图灵完备相去甚远,只能博君一笑。

程序我写成了python代码,便于大家脱机调试。

(题面见附件)
图片描述

从我个人的观感上来说,现阶段的 AI还不具备逆向研究真正稀缺的能力:

尤其是2和3,AI做得很差。

AI远没有超出的不是人类智慧的总和。尤其是Agent的广泛应用,使得以 抄袭存量思想 + 蛮力尝试 为主的AI,显得异常惊艳。然而它只是人类存量思想的投影,在更多的创新、体系化的任务上,AI表现得极为笨拙。

比如:

打个不恰当的比方:AI或许能比肩陈景润1+2的高度(即:把已知的筛法技巧应用到极致),但远达不到伽罗瓦创建群论的高度。

我们真正该反思的是:人类安全研究员是否一直在自我抄袭?所以当AI具备存量机制的泛化能力后,我们才会显得那么不堪一击?

    M = (Q,q₀,Σ,σ,δ)
    δ(q,a) = (q',b,D)
    a = 3
    b = 4
    c = a * b
    × |  2  3  4  5  6  7  8  9
    2 |  4  6  8 10 12 14 16 18
    3 |  6  9 12 15 18 21 24 27
    4 |  8 12 16 20 24 28 32 36
    5 | 10 15 20 25 30 35 40 45
    6 | 12 18 24 30 36 42 48 54
    7 | 14 21 28 35 42 49 56 63
    8 | 16 24 32 40 48 56 64 72
    9 | 18 27 36 45 54 63 72 81
    mov r1, 3
    mov r2, 4
    mov r3, mul[3][4]
    mov next_ea, 'add eax, ebx' 

传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!

最后于 14小时前 被逆向大聪明编辑 ,原因:
上传的附件:
收藏
点赞 ・4
打赏
分享
最新回复 (4)
雪    币: 2586
活跃值: (3594)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2 楼
牛
14小时前
0
雪    币: 915
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3 楼
学习学习
11小时前
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4 楼
666
7小时前
0
雪    币: 317
活跃值: (2602)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
5 楼

也许跳出VM/Visual Machine虚拟机的思想能够有新的答案,虚拟机保护产品目前已经非常成熟与稳定、其理论最早在2002年提出,2004首先由俄罗斯的VMP公司实现并应用。目前软件保护业内最强理论是2012年由IBM以及UCLA提出的多线性拼图技术。(引自玩命版主的:玩命的销售日志 2017.7.31)个人认为在AI时代下,程序控制流保护方面,在针对Trace/仿真技术上应该利用AVX之类Unicorn无法模拟的指令集,在MBA混淆方面利用特定的条件,利用shl/shr/idiv之类的指令进行混淆,在添加程序保护的时候做一次编译优化,将ifelse变更为基于某个状态hash的跳转,总之,尽可能减少面对相关技术暴露的信息。


我在分析未知混淆的时候,会让Agent在上下文快满的时候,问一句,如果当前的程序解密是块拼图或地图,那我们现在知道了什么,还有哪些是未知的。这样,就为我们的下一步判断提供了依据。


备注:AI人工智能的发展速度在未来一年内将放缓,投入回报不及预期。虽然内地股市行情不好,但明年美市虹吸全球市场产生的泡沫也有概率破灭。真正的价值应该会在泡沫破灭后真正的显现。

最后于 5小时前 被zZhouQing编辑 ,原因:
5小时前
0
游客
登录 | 注册 方可回帖
返回