首页
社区
课程
招聘
[原创]看雪CTF从入门到存活(五)坦克与法师
发表于: 2018-12-16 20:15 8488

[原创]看雪CTF从入门到存活(五)坦克与法师

2018-12-16 20:15
8488

看雪CTF在业内享有盛誉 每年两届 都是精英云集
笔者参加看雪赛事不久 有了一点体会 想与大家分享
不妥之处 万望指正

笔者认为 看雪CTF的防守作品(以下简称CM)应该追求的设计目标是:设计者知道一条捷径可以容易得到正确序列号 而其他人难以找出这条捷径
这条捷径不可以是“设计者拥有一个私钥” 但可以是“设计者隐藏的某个(破解者可以发现或者猜到的)秘密”
这个秘密可以有很多形式:某种逆向的技巧 某种减少穷举空间的技巧等等
历届比赛的防守方 不论是萌新还是dalao 都在上演各种‘秘密’
可谓百家争鸣百花齐放 一片繁荣

同时 我们也看到了几个现象
1)难存活:这些秘密虽然形式很多 但真正能有效阻挡破解者的 不多
2)见光死:虽然有的作品成功阻挡了破解者48小时 但其方法是不可重用的 如果再次使用是挡不住破解者的
3)不划算:即使有些方法可以再现 但再现成本很高 远高于破解者所要付出的代价

于是 笔者曾提出过一个问题:是否存在一种终极方法 能够低成本地产出CM且能阻挡破解者?

为了看清本质 我们从起点开始分析

CM的运行方式是:用户输入序列号 CM判断是否正确并给出提示
不论CM里面是怎么干的 宏观上可以认为是:利用输入的序列号 进行了某种运算 判断计算结果并提示

运算的输入 是破解者可以任意指定的
运算的正确理想结果 是存在CM中的(即便可以各种伪装 但高手是一定能找到的)
运算的过程 是破解者可以看到的(即便可以各种anti-debug 但高手总是能看清滴)
由于我们关注的是存活问题 所以我们只关注破解者是高手的情况
因此 我们就不讨论那些伪装和anti技巧了

具体实现时 还可以有多种变化 例如:可以把序列号拆成多个部分或者视角 分别验证
验证结果 可与 可或 可串联
所谓串联 是指用前一个运算的结果 当做下一个运算的条件
如果前一个验算不正确 则无法展开下一个计算(例如 SMC)
但这些变化只是‘量’上的区别 并无‘质’上区别 我们在此也不讨论了

于是 我们回归到问题的本质(假设CM中只有1个运算过程)
1)攻击模式:破解者已知运算过程 已知运算结果 寻找正确的运算输入
2)防守模式:防守方力图在假设正向运算公开的前提下 加大从‘结果’逆推‘输入’的难度 且需要保留一条逆推捷径

防守方要设计出‘难以逆推’的运算过程 是容易的(例如 单向函数)
要设计出‘只有设计者才能快速逆推而其他人难以逆推’的运算过程 也是容易的(例如 单向陷门函数)
难点在于:这条‘快速逆推捷径’必须是攻击者基于人类公开共享知识能够推导或猜测出来的,或者在有限时间内能穷举出来的(否则就违反了看雪CTF比赛规则和比赛精神)

那么问题来了
捷径不可以是不公开的密钥 那还能是什么呢?
这个问题看似令人困惑 但只要我们参考一下“信息对称条件下的零和博弈”模型 答案马上就清晰了 捷径只能是破题方法
也就是说 CM的安全要基于:让攻击者不知道该如何逆推正确输入
而不是 攻击者知道正确逆推方法 只是逆推时间较长而已

但是 紧接着问题又来了
攻击者是知道正向算法的 凭什么攻击者就找不出逆推算法呢?
有这么几种情况
1)这种正向算法根本就不可逆(例如 SHA-512)。这种情况显然是违规的 不予考虑
2)逆推方法是基于某种生僻的专业知识(例如 要求破解者根据一个阿尔巴尼亚语提问者的情绪给出适当的回答 CM使用一个经过深度学习训练好的网络来判断回答是否正确)原则上 这类出题思路是符合看雪比赛规则的 而且有可能在比赛中胜出 但这种方法会使得参赛者参与度很低 有悖于比赛精神 不予推荐
3)不超出广大参与者都应该具备的知识背景 要想阻止攻击者找出逆推算法 唯一能挡住攻击者的 笔者认为 就只剩下:想象力!

想象力 是不以‘秘密’的形式存在的
它只受限于破解者的思维能力 和富裕程度(开个玩笑啊)

The only limitation is imagination.
---big hero

如何考验破解者的想象力呢?
这个问题本身就很考验设计者的想象力!

让我们来看一个例子吧
老师出了一道几何证明题 全班同学都做不出来 只有小明走到黑板前 画了一条辅助线 于是全班同学都豁然开朗
这就叫 想象力!

作为破解者 小明显然比其他同学聪明
这个 我们就认了
但是 出题的老师真的要和做题的小明一样聪明吗?

其实 出题老师并不需要那么聪明
之所以老师能够出得出来这样的题 是因为老师在出题的时候 是通过这条辅助线把题目设计出来的
只不过 在发布题目的时候 老师故意抹掉了辅助线
只要做题人能够想得出来 在合适的地方添加一条辅助线 此题即可解开 否则难解

笔者认为 这才是看雪CTF的最佳出题方式!

换句话说 一个好的CM是这样设计出来的
1)选择一个领域 能够用数字化的方式进行表达
2)在已知辅助线的情况下 设计出正向运算过程 在给定的正确输入下 得到正确结果
3)抹掉辅助线 只保留正向运算和正确结果 要求破解者找正确输入
假如破解者能够找到正确的画辅助线的方式 那么此题易解 否则难解

上面提到的‘辅助线’ 只是一个形象的比喻
在真实环境中 并不一定真是一条线
那么 在真实环境中 该怎么设计这根辅助线呢?

辅助线的本质 是一种联系 它将2个或多个概念联系了起来
在CM中 辅助线可能是(但不仅限于):
1)看起来两个独立的处理流程之间的内在关系(例如 暗风吹雨中的spectre隐通道)
2)输入输出数据之间的数学关系(例如 cm2017-ccfer中的频域滤波)
3)看起来是一种语义 但实际是另一种语义的对应关系(例如 九重妖塔中的2层VM指令流)
破解的关键点 恰恰就是 找出或者猜出这种联系

一旦破解者开始怀疑 这两者存在某种特定联系 那么这就是破解之门即将开启的前奏
破解者会用各种方法来验证其猜想
通常 验证猜想的时间不会太长

我们一层一层抽丝剥茧 终于要走到问题的核心上了
要想挡住破解者关键就在于:不能让破解者轻易地知道
1)到底哪两个者是存在关联的
2)到底存在什么样的关联
(注意:一旦猜到了 验证起来是很容易的)

到这里 大家应该都明白了我想说什么吧
如果想在看雪CTF比赛中存活下来 讲人话 有2个方案:

1)坦克方案
为了让破解者找不到哪两个对象有关联 只要让对象数量多起来就好了
但是 比赛规则规定了CM的filesize 所以直接对象的数量不可能太多
于是 我们可以把注意力转向‘直接对象’组合出的‘间接对象’
只要程序里值得怀疑的‘可能有关联’的间接对象很多 而且相互之间的关系都很相似
破解者就难以从茫茫对象中找出真正有关联的对象(组合)
设计方法:CM中对象地位对等 且组合数量众多 难以找出对象满足组合关系
坦克座右铭:直白而血厚

2)法师方案
如果不想把数据量搞得很大 程序中值得怀疑的对象自然就会少 甚至只有两个对象
那就要想办法阻止破解者找出这两个对象之间的具体关联关系(例如 魔法森林拟群运算的输入输出)
在对象之间设计足够复杂的函数关系 只保留函数结果 却要求破解者去猜测函数的显式表达式
设计方法:对象数量不多 但其间的数学关系隐晦难猜 妨碍逆推求解公式
法师座右铭:女人只有一颗心 可你就是看不懂

实操中不排除混合使用坦克方案和法师方案

好,方案已经有了
那是不是只要遵循这2种方案就一定能设计出能存活的CM呢?
答案是否定的!因为还有这些方面不能忽略:

1)坦克方案中的对象数量众多 要特别当心存在设计者没想到的多解和非预期解(感谢んеХег在这个问题上的垂手指点)
要解决这个问题有2个办法:
1.1)将对象分散在多个正交基上 从数学上能证明 不同正交基上的对象之间不可能产生指定关联(例如 叹息之墙中的9个子群)
1.2)扩大输入空间 降低关联空间 使得碰撞概率极低 可能性忽略不计(Riatre对七十二疑冢是如何避免多解 已有透彻论述)

2)法师方案中的函数关系要足够复杂且不可预测 (感谢po叔指点 让笔者对‘猜’的套路有了一定的了解)
要解决这个问题需要把握好一个度!函数关系不能容易被猜到,但也不能过于偏激!
笔者在摸索这个度的过程中 从易到难 逐步加大难度 逐步加深埋藏线索的深度(魔法森林证明 目前的埋藏深度可以阻挡大多数破解者 但还不足以挡住个别高手)

除了以上2种方案以外 还存在着一种非理性因素 也能够帮助存活:皮肤压制
虽然我们都知道 皮肤并无太大实际功用 但是当你面前真的出现一个冰封战神时 很多人还是会胆怯的 其战斗力和判断力都会受到影响 甚至会放弃对抗(例如:2006年cnbragon那道RSA768题)
不过 皮肤压制只能用于吓唬一般玩家 对顶级高手基本上没用 所以需要与其它困难问题混合使用
设计方法:用一个知名难题来伪装CM 吓退破解者
皮肤座右铭:我爸是李刚(有时候 我爸真的是李刚)

如果正确使用了上述方法 那么就有机会设计出能撑过48小时的CM
而且笔者认为 可以设计出很多个

不论是坦克 还是法师 要想高效安全地设计出CM 都是有规律可循的
所以 在每次实现的时候 即使设计者都有一定的发挥空间 但要想不放弃上述基本设计原则 其实设计出来的作品 多少会让人觉得似曾相识
(例如 叹息之墙与七十二疑冢很相似 密室逃脱与魔法森林很相似。尽管它们的破解难度有很大区别)
他们就像培育水稻和玉米一样 只要掌握了正确的基因修饰技术 就能不断改善品种 产量会越来越高 抗病虫害能力越来越强
笔者相信 沿着这些系列不断推进作品 终有一天它们能够支撑48小时以上

可能有人会问 难道只有这些坦克和法师能存活吗?
当然不是!
在前面的推导过程中 曾经在很多个环节 都舍弃了许多变化和分支
但在实际操作中 这些变化和分支 都是有一定‘阻止破解’的作用的
而且 将多种防护方法进行组合 效果会强于 单单指望着一种貌似最强的防护
这样一来 就算不是坦克或者法师 也一样有机会撑过48小时
而且实际上 在这些过程中 即使是那些没有存活下来的作品 对于攻防双方来说 也都是学习和长进的机会 是好的

“攻防双方都有长进!”
这才是值得我们追求的目标!

笔者之所以不愿意用组合防护 每次出题都是‘单吊一个点’
有时还会冒着被人误解为‘故意放水’的风险 给破解者一点鼓励和提示 引导破解者直扑核心
甚至不惜在看雪CTF中屡战屡败(但从未就核心问题给出过任何提示)
其原因
1)笔者希望看清每一种防护手段到底能抵御到什么程度(而组合防护虽然可以提高胜率 但是会让研究工作变得困难 看不清各个手段的独立作用)
2)笔者能力有限 见识有限 在当时那个历史时期 也就那个水平 已经尽力了(即便使用了组合防护 不给任何提示 也苟延不了几个小时)
笔者这么选择 不是为了赢得比赛 而是为了研究比赛 促进比赛
希望笔者的研究成果能够对大家有所帮助 这些付出就都值了

感谢んеХег亲手指导,让笔者在2天的时间内以超越常人一年多的速度提升。
感谢海风月影促膝夜谈,让笔者眼界大开思路升华。
感谢po叔时常分享破解经验,让笔者少走了不少弯路。
感谢Riatre的破解与分享。破解成功 就是笔者的进步之源。
感谢netwind公正裁判,也给了笔者修改bug的机会。
感谢kanxue搭建了如此优秀的平台,聚拢一帮精英。
感谢所有帮助过、击败过看场雪的朋友们!


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2018-12-16 20:17 被看场雪编辑 ,原因:
收藏
免费 12
支持
分享
最新回复 (17)
雪    币: 47147
活跃值: (20445)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
写的很深刻,欢迎大家参与讨论
2018-12-16 21:47
1
雪    币: 1829
活跃值: (1377)
能力值: (RANK:50 )
在线值:
发帖
回帖
粉丝
3
2018-12-16 21:59
1
雪    币: 13059
活跃值: (5723)
能力值: ( LV5,RANK:77 )
在线值:
发帖
回帖
粉丝
qux
4
佩服
2018-12-16 22:17
1
雪    币: 6051
活跃值: (1441)
能力值: ( LV15,RANK:1473 )
在线值:
发帖
回帖
粉丝
5
个人感想:
1.密码算法是最核心的,一个优美的密码算法可以挡住绝大多数人的进攻。从某种意义上说,ANTI只是延时,一个难解的算法才是活下去的关键。
2.算法都是见光死,自己设计算法又真的太费心,最简单有效的办法是用成熟但比较小众的产品,比如说游戏,如果没玩过游戏靠逆向来解析游戏架构,复杂度会成级数上升。但如果玩过游戏知道游戏规则,又会造成直接通关的捷径。
3.最重要的是要隐藏自己的想法,目前看比较优美的隐藏方式有:发现DEBUG时自修改来隐藏,加花指令或破坏堆栈平衡防止反编译,使用VM隐藏,制造大数据多个函数多级指针来大隐隐于市,等等。
2018-12-16 22:18
1
雪    币: 23080
活跃值: (3432)
能力值: (RANK:648 )
在线值:
发帖
回帖
粉丝
6
tql
每道题目给出的提示很有意思,故事性强,高手可以看出其中奥秘。而我等小菜鸟只能看到故事表层意思,还需要多被大佬们蹂躏蹂躏啊!
2018-12-16 22:34
1
雪    币: 334
活跃值: (22)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
,有收获。写的深入,把CM玩法分析的贴近本质,学习了
2018-12-16 22:40
1
雪    币: 26136
活跃值: (1409)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
分析透彻,深有感触。前排占楼,想知道234哪去了?为何只有一和五?
2018-12-17 00:24
2
雪    币: 284
活跃值: (3599)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
9
高手过招,观众无法发言。
2018-12-17 09:37
1
雪    币: 2046
活跃值: (265)
能力值: ( LV7,RANK:104 )
在线值:
发帖
回帖
粉丝
10
挽梦雪舞 分析透彻,深有感触。前排占楼,想知道234哪去了?为何只有一和五?[em_1]
瞄准,捕捉,捕捉成功
2018-12-17 23:56
1
雪    币: 8209
活跃值: (4518)
能力值: ( LV15,RANK:2473 )
在线值:
发帖
回帖
粉丝
11
道士有意见
2018-12-18 12:54
1
雪    币: 6435
活跃值: (441)
能力值: ( LV12,RANK:831 )
在线值:
发帖
回帖
粉丝
12
简单说两句,我之所以对你的这种出题方式有意见,是因为我认为这种出题方式假设了“出题方可以出一个自己做不出来,甚至没有思路怎么去解的问题”。

我认为出题方需要做到在“完全忘记自己这个题是怎么出的”的情况下依然要能对如何解决这个问题有一个清楚的认识(可以不去实际做,但在必要的情况下要能在不加对本题的任何先验知识的情况下说明这个问题是可解的),也就是说要给出一种可以发现自己埋藏的秘密的路径,这个路径本身不能包含任何秘密,而不能只给出这个秘密本身。如果出题方不需要做到这一点的话,那禁止出一个“设计者拥有一个私钥”的题目又有什么意义呢?我大可以出一个伪装起来的我拥有一个私钥的题目,事后只要说我不小心设计出了一种在密码学意义上有一定强度的问题就可以了。简单来说,如果出题方不需要提出一种从零开始的攻击路径,你埋藏的这个“秘密”和私钥之间的界限,在比赛的意义下就是模糊的(当然我们都知道 obscurity != security,所以二者还是能区分的,但想一想,区分的方式是什么呢?) 。

而如果出题方需要做到这一点,那么你所谓的 “低成本地产出CM” 将不再成立,因为按照你这个思路出完题目之后,出题方需要对自己的题目进行攻击验证,这当然依然比做题的人需要耗的精力少不少(因为做题人往往缺乏相应的背景知识,需要现场学习),但并不会远低于破解者所需要付出的代价。一种例外情况是你去找一些现成的,已经做好的双向的结果,然后把它们出成 CrackMe (比如我赌五毛你肯定读过 Shcherbacov 全家桶)。
而对于 CrackMe,命题的题材最好是能在软件保护这个猫鼠游戏上给人带来一些启发的。而将同样的一种混淆手法更换问题背景反复使用并不符合这一点。举个例子,我大可以随便找一个已经被攻破到不成样子的密码算法(可能要稍微再削一削)来出个题;或者找一些存在 weak key 或一些条件下会变弱的密码算法出成题要求还原 key,然后让破解者观察、猜,然后实现对应的攻击去吧,彻底让这个比赛变成读纸大赛,意义又何在呢?

这样子“批量产生CM”的方法并不通用于软件保护的过程,这本来就是一个猫鼠游戏,我认为你想改变这一点的“执念”很难达成,而你现在的想法是一种“偷换概念”,所以我才说这是在打规则的擦边球。

------------------------------------

当然,作为一个兴趣稍微有点广泛的人,我是很愿意尝试解这样的题目的(前提是验证过真的可解),毕竟可以增长见识;而且从参与比赛的角度来看,由于看起来会的人不多,做出来之后就令人十分安心 :P
最后于 2018-12-19 04:24 被Riatre编辑 ,原因:
2018-12-19 04:06
1
雪    币: 10845
活跃值: (1054)
能力值: (RANK:190 )
在线值:
发帖
回帖
粉丝
13
Riatre 简单说两句,我之所以对你的这种出题方式有意见,是因为我认为这种出题方式假设了“出题方可以出一个自己做不出来,甚至没有思路怎么去解的问题”。我认为出题方需要做到在“完全忘记自己这个题是怎么出的”的情况下 ...
天哪!
昨晚我刚刚写了一篇文章 还没来得及发
内容跟你的回复几乎一样 甚至描述的用词都是一样的
网友说“心有灵犀”,真的不过分呐!

不过 我的结论与你的不同

你的观点是:这种出题方式“彻底让这个比赛变成读纸大赛,意义又何在呢?”

我不这么认为
不论我过去的出题方式多么让人感到无趣 但那些都只是我的研究过程 而我最终的研究目标 一定是一个“有实际应用价值”的软件保护方式 而绝非一道“可以难住世人”的crackme
其研究过程可能是曲折的痛苦的 但其目标一定是值得期待的!
所以 我还会坚持我的研究方向 相信有一天 我的研究成果不会仅仅是一个玩具!

虽然我们的观点不同 但令我惊喜的是 世上居然有另一个人 能够真的知道我在想什么 甚至能够在我说出来之前 先说出来!这世界实在太奇妙了

感谢你的提醒 昨天po叔也私下批评了我的部分想法(虚心接受) 
我会在下一届的比赛中换一种前所未有的出题方式(更贴近于实战)
敬请期待
最后于 2018-12-19 09:25 被看场雪编辑 ,原因:
2018-12-19 08:01
2
雪    币: 23080
活跃值: (3432)
能力值: (RANK:648 )
在线值:
发帖
回帖
粉丝
14
可以在题目中增加点软件保护相关的“关卡”,就算我们解不了最终的算法,但还可以体验逆向与调试的乐趣呀
2018-12-19 10:55
1
雪    币: 10845
活跃值: (1054)
能力值: (RANK:190 )
在线值:
发帖
回帖
粉丝
15
KevinsBobo 可以在题目中增加点软件保护相关的“关卡”,就算我们解不了最终的算法,但还可以体验逆向与调试的乐趣呀[em_13]
就像叹息之墙那样吗?
2018-12-19 10:58
0
雪    币: 23080
活跃值: (3432)
能力值: (RANK:648 )
在线值:
发帖
回帖
粉丝
16
叹息之墙那道题之后我看到您说“下次再出题 要么不混淆 要么会升级混淆策略”,毕竟您的目标是存活,可能觉得加了代码混淆也未必能够增加存活时间,于是把全部注意力转移到了密码算法上。至于加不加软件保护方面的“关卡”,还是要看出题的目的和针对的破解者。
作为我这样的CTF菜鸟肯定希望题目能够大众化一些,这样才能更多参与进来,多做一些题目,打怪刷副本升级。
2018-12-19 11:32
1
雪    币: 2095
活跃值: (344)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
分析透彻,深有感触
2018-12-19 12:42
1
雪    币: 10845
活跃值: (1054)
能力值: (RANK:190 )
在线值:
发帖
回帖
粉丝
18
KevinsBobo 叹息之墙那道题之后我看到您说“下次再出题 要么不混淆 要么会升级混淆策略”,毕竟您的目标是存活,可能觉得加了代码混淆也未必能够增加存活时间,于是把全部注意力转移到了密码算法上。至于加不加软件保护方面的 ...
是的 我的确这么说过

叹息之墙那题的混淆 说实话 不是我设计的 而是我临时请来一位朋友设计的(当时他的大名也出现在了出题团队 看场雪club 的名单中)

我现在还不能在混淆方面有什么实质性的推进 不是因为我不想或者不愿
而是因为不会!

我甚至没有发现任何把握:用某种混淆方法就能确定挡住破解者(不论这种方法我现在会不会)

最后于 2018-12-19 13:23 被看场雪编辑 ,原因:
2018-12-19 12:53
2
游客
登录 | 注册 方可回帖
返回
//