Archaia(武汉科锐学员队)
846235136
见附件
用户名 : FE0C37052AED0E33
序列号 : 7D4DBA7A9C2EF1A8EF848BC880B83170431F37E599048DBB88C306BC403579D1
用户名 : KCTF
序列号 : B91AE5FCDA57D87406968CBDB8829799790A77302D7E8754B705894489B37A10
此题《千里寻根》为"KCTF2019Q3第十题《传家之宝》"和"KCTF2019Q4第六题《三道八佛》"的升级版本,
在经历前两次比赛后总结不足,修改更新出来的作品.
此题风格上和之前两道题目一样, 依旧是没有在算法上设卡, 主打代码流.
主要的设计思路就是
代码长长长, 并且设卡阻止破解者"眼看手跳快速pass大量框架代码直捣黄龙"
1.《传家之宝》《三道八佛》两道题目是windows32位的应用程序, 经过代码重构(整体思路和程序大体流程基本上没变)这次提交的题目《千里寻根》是windows64位的应用程序
2.三道题目作战思路都是使用"蜗牛壳":
使用SMC技术一边执行关键算法代码,一边解密"下一代蜗牛".
首代蜗牛负责输入用户名和序列号.
中间的蜗牛负责背着后代的壳(后面层的加密代码), 行走一小步(执行一点关键算法代码), 再产生出下一代蜗牛(解密下一层的代码).
末代蜗牛负责验证和输出结果.
《传家之宝》共2880层, 《三道八佛》共1400层, 这次《千里寻根》共2021层.
(1)《传家之宝》《三道八佛》两道题目因为"中间的蜗牛"特征过于明显, 很容易就写出了跟踪脚本, 分离并整合出关键算法代码.
所以这次提交的题目对"中间的蜗牛"进行了变异处理(代码随机混淆).
"中间的每一代蜗牛"都干着相同的事情, 可是都是长得完全不一样.
(2)《传家之宝》《三道八佛》两道题目为了影响攻击者写跟踪脚本, 加入了多种反调试手段(异常, 时间等).
这次提交的题目中, "蜗牛壳"删除了原有的所有反调试手段.
3.在"蜗牛壳"的基础上, 另外还给应用程序加了个"PE加密壳", 这是《传家之宝》《三道八佛》两道题目中没有的.
"PE加密壳"的作用是CRC校验, 反调试, 加密原程序的导入表项
4.关键的验证算法上没有过多设计, 因为此题重点在壳上.
使用的是《三道八佛》里的算法加上稍作修改的base64算法
PE加密壳:
CRC校验: 只校验外壳代码, 在攻击者patch外壳代码的时候会导致解压缩代码节数据不对
反调试: 使用了两种反调试"IsDebuggerPresent"和"模拟NtQueryInformationProcess"
加密导入表: 如果不脱此加密壳就着手研究, 在"首代蜗牛"和"末代蜗牛"调用API的地方, 不能直接看到被调用API的名字和地址
蜗牛壳:
SMC加密: 使用简单的加密算法保护后代蜗牛的代码, 防止破解者看到未来太远的代码
地址随机化: 每一代蜗牛展开蜗牛壳, 抛出下一代蜗牛时, 随机指定下一代蜗牛的执行地址
切片技术: 将核心算法的代码切成切片, 然后将每个切片贴到每层壳上(有可能有的层是没有核心算法代码的切片的), 每层壳被执行的时候, 相应的切片也会被执行.
代码独立: 蜗牛壳在运作的时候, 不调用任何外部的API, 不使用外部的堆栈
对抗脚本: 破解者在看了前面几层壳的架势之后, 不会真的一层一层单步跟踪, 而会写脚本脱壳取肉. 这是对比之前两题主要改进的地方, 利用混淆工具对中间层进行随机混淆, 加大破解者寻找蜗牛壳行为特征写脚本的难度.
1.脱去最外层的"加密壳", 得到只有"蜗牛壳"的应用程序
"蜗牛壳"和最外层的"加密壳"不会相互依赖, 所以可以确保最外层的"加密壳"脱掉后能正常运行, 当然可能大佬不需要脱"加密壳"就能进行下面的破解步骤.
脱壳比较简单, 找到OEP(0x140001088), dump, 修复导入表项(导入表项只有system/scanf/printf/GetModuleHandleA/ExitProcess/VirtualProtect六项), 即可完成脱壳.
2.使用x64dbg(或者ida等其他工具)的trace功能, 得到"蜗牛壳"所有的执行过的代码
(1)从"首代蜗牛"输入完成一直跟踪到"末代蜗牛"完成比较输出结果, 得到中间所有的代码.
(2)观察并写代码对上面得到的代码进行优化:
去掉跳转代码
多行汇编代码合并成一行(比如把mov rax, 1和add rax, 2 合并成mov rax, 3)
(3)经过上面的步骤就能发现, "中间的每一代蜗牛"代码基本上一样, 根据特征分离出关键算法代码
3.根据关键算法代码写逆算法, 此题在算法上没有过多设计, 参考大佬们写的《三道八佛》wp算法部分和base64算法稍作修改即可写出KeyGen.
https://bbs.pediy.com/thread-256746.htm
https://bbs.pediy.com/thread-256835.htm
相信有不少选手想尝试思路1的"trace所有的执行过的代码", 都会遇到一个很尴尬的问题: 很难trace完, 或者莫名其妙trace结束了.
笔者在自己测试时候, 使用x64dbg的trace into功能, 大概跟踪半小时后, x64dbg会停止trace, 直接把程序运行起来, 而且还附带着"系统库名称符号不见了"/"Ctrl+G无法跳转地址"等一系列奇怪的现象. 这应该是x64dbg的BUG吧, 输出数据太多导致无法alloc内存.
断掉trace的念头(trace可能是条不归路), 自己跟踪个一两层代码找特征, 然后编写调试脚本能整层整层跑蜗牛壳.
要想破解蜗牛壳保护的程序, 最关键的步骤就是从万千代码海中提取出"肉代码", 这也是此题的难点所在.
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-5-23 12:28
被kanxue编辑
,原因: