Mysterious,修改寄存器+内存分析
1.题目介绍
描述:自从报名了CTF竞赛后,小明就辗转于各大论坛,但是对于逆向题目仍是一知半解。有一天,一个论坛老鸟给小明发了一个神秘的盒子,里面有开启逆向思维的秘密。小明如获至宝,三天三夜,终于解答出来了,聪明的你能搞定这个神秘盒子么?(答案为flag{XXX}形式)
来源:BUUCTF-2019
场景:暂无
附件:可执行文件,文件名“caddc1a7d6bb480595bf4ec4644c106e.exe”,程序图标是百度的标志,带有界面。

2.文件分析
程序打开后是一个小窗口,写着“Input the password(输入密码)”,输入错误的“密码”或者不输入任何字符,程序无任何反应——没有字样提示,也没有消息框弹出。有的情况下多次输入错误,程序直接退出。

把文件放到Exeinfo PE中发现其是由VC6 MFC编写的,没有加壳。如图。

3.逆向分析
由于这里是带界面的C++程序,程序的入口函数是WinMain,首先双击IDA中左侧函数小窗的WinMain(x,x,x,x),然后双击指令“jmp _WinMain@16_0”中的单词“_WinMain@16_0”,双击指令“push offset DialogFunc”的DialogFunc,双击“sub_401090”,就是需要分析的代码段了。如下图示。

3.1 思路1
思路1是比较偷懒的方法,在逐语句调试时自己修改寄存器的值来使得语句跳转到提示成功的路径。

这张图标定了3个方框,在调试的过程中发现输入的字符长度不能超过6(cmp eax, 6);call _atoi 指令表明将字符串转换为数值型;cmp [ebp+var_108], 7Bh 表示将数值与7Bh(十六进制)比较,7B转换成十进制是123。同时注意是edx寄存器加1后得到的7Bh数值,因为前面有add edx,1指令。
在测试的时候,笔者在文本框中输入三个字母“abc”,而“abc”传入到atoi函数的参数中是不能化为数值型数据的,所以返回值为0,[ebp+var_108]内存中对应的前面几个值(第2、3、4个位置)也为0。
基于上述分析,至少文本框里应该输入字符串122(7Ah)。输入之后就能跳转到一下代码段了。以下定义了4个路径,其中“路径4”是提示成功并显示flag的代码段。
所以在代码执行到路径1、2、3中cmp指令时候,分别将eax, ecx,edx寄存器的值改为78h, 7Ah, 79h。欺骗程序执行到路径4以获取flag。所以弹出对话框如下。

对话框里显示的正是flag。
3.2 思路2
那么思路2正是分析出在文本框中输入什么字符串才会成功的显示flag。
仍然动态调试并逐语句执行,首先在文本框中输入“122”再观察。路径1中指令“movsx eax, [ebp+var_101]”执行后发现eax的值变为了0。后面路径2、路径3的ecx,edx也是被赋值为0。说明字符串“122”后还应该有3个字符,再进一步调试发现,其实后三个字符在ASCII表中分别对应78h, 7ah, 79h的字母分别为“x”、“z”、“y”。那程序的“密码”是不是“122xzy”呢?也不是,调试后发现路径2是判断最后一个字符,路径3是判断倒数第二个字符,所以位置颠倒一下后密码为“122xyz”。

最终flag是flag{123_Buff3r_0v3rf|0w}
4.总结
熟悉VC6 MFC框架下可视化应用程序的设计,至少要知道带窗体的可视化VC++程序是如何执行的,有哪些重要函数。这篇文章从直接修改寄存器的值(知道常见的跳转指令),循序渐进分析两个方面来获取程序的flag。




