我在哈布雷(Habré)上多次提到
Check Point安全学院计划:其实质是
Check Point公司在夏季宣布了“夺旗”格式的比赛,参与者的过去经验并不重要,而仅仅是他解开网络的能力难题。 根据这次比赛的结果,该公司招募了20名参与者参加为期3个月的网络安全专业课程,并且从该课程开始时所有参与者都将获得KB专家的全薪,并有义务在课程结束后两年内在公司工作。
在CTF比赛中,旗帜甚至可以是图片,例如这样。参赛者的选拔工作已于8月完成,但比赛网站将持续运行至明年夏天,我邀请那些希望报名并出于体育兴趣尝试的人参加比赛。 比赛由12个不同复杂程度的难题组成,评分为10到150分。
在这里,我想解析“惊喜”类别中的“测试我的耐心”难题。 她中等难度(50分),这是她的全文:
你好
我们在本地制表者的计算机上找到了此可执行文件。
有传言说,制表师是唯一成功破解它的人。
认为您和制表师一样好吗?
注意:此文件绝不是恶意文件
通过引用-Windows的32位二进制文件,
某些杀毒软件对此
发誓 ,但是如果您仍然运行它,它将看起来像这样:

二进制文件内部被加密; 它拒绝在调试器下运行; 如果尝试在调试器运行时将其连接到该调试器,它将立即终止。 可能是Check Point的专家将他们的难题包裹在一个从某种恶意中借来的加密打包机中。
我们如何猜测制表商所组成的数字?
有两种方法。 第一个可以有条件地称为“有力量,没关系”:如果无法实时调试程序,那么我们将调试死的程序!
启动32位任务管理器(\ Windows \ SysWOW64 \ taskmgr.exe),右键单击神秘进程,然后选择“创建转储文件”。 (用于32位进程的64位任务管理器创建了wow64cpu仿真器的转储,这更难使用。)
我们查看转储,发现至少其中的行已被解密:

但是带有隐藏数字或标志的行尚不可见。
我们转向主要口径武器:WinDbg(X86)-> Open Crash Dump ...

我们想看到的行在内存中的位置写着“好,我的朋友!”?
lm
命令允许您确定二进制文件是从
01140000
加载到
015b2000
; 然后
sa 01140000 015b2000 "Good job my friend!"
在
0115a0d0
找到搜索字符串:

现在,让我们查找该行的打印位置:也许某个命令包含的字节
d0 a0 15 01
对应于您要查找的行的地址? (
sb 01140000 015b2000 d0 a0 15 01
)
祝你好运! -发现了这样的团队:

此命令的代码是什么? (
ub 011412f7; u 011412f7
)

我们看到,根据功能
01141180
的结果,打印的是所需的消息,还是“错误的...”。
功能代码
01141180
占据三个屏幕; 很容易看出这是
strcmp()
的实现,其中添加了
Sleep(700)
调用。 目前尚不清楚为什么会有
Sleep()
; 但它仍然不会影响函数的结果,因此我们最好弄清楚要比较的字符串:

ebp-14h
两个等于
ebp-14h
和
ebp-24h
指针; 第二个作为
011410b0
传递给函数
011410b0
。
这不是要求隐藏号码的功能吗? 让我们检查调用堆栈(
k
):

是的,是她!
难题的一般方案现在很清楚:将用户的预感存储在
ebp-24h
,将
ebp-14h
的数字存储在
ebp-24h
ebp-14h
,然后将它们进行比较,然后打印“好,我的朋友!”或“错了……”。
剩下的就是从堆栈帧中提取隐藏的数字。 我们已经从调用堆栈中知道了他的
ebp
:

来吧,来吧...

成功! 您可以打开一些美味的软木塞。
但是留下了三个神秘的东西,没有解释:
- 为什么
Sleep(700)
的strcmp()
Sleep(700)
内调用Sleep(700)
? - 为什么当我们输入隐藏号码时,程序在打印“我的朋友好!”之前冻结了十秒钟?
- 制表师与这个难题有什么关系?
因此,事实证明,还有第二种(更智能的)方式来猜测所猜测的数字。 如果您只是随机尝试数字0-9,则很容易注意到该程序在9个数字上“挂起”了一点。 如果尝试使用数字90-99,则可以看到在数字98上程序“冻结”的时间是原来的两倍。 (发现其胆量之后,我们已经了解了问题所在:每对字符的成功比较会导致0.7 s的延迟。)要解决这个难题,甚至无需启动调试器,只需选择下一位数字就可以了,这样,答案答案之前的延迟就可以手动增加使用精确的秒表或简单的脚本。 因此,当测量和分析直至错误消息的时间时,编译器暗示了一种
攻击密码算法的长期方法 。
但是,在我看来,学习如何获取包裹在未知加密打包程序中的程序既有趣又有价值:-)
请注意,我们不需要弄清楚二进制文件是如何加密的,或者带有您看到的数字的字符串如何显示在堆栈上(我们在转储中看到它不在字符串常量中)-我们设法做好了准备,为此大约一打WinDbg命令就足够了。