Reversing.kr 4 5

Catalpa 网络安全爱好者

Reversing.kr 上面的题目。

04 Music Player

第四题增加了一些难度,打开文件,是一个简单的音乐播放器,但是载入的歌曲最多只能播放1分钟,根据题目提示,如果能够使它播放超过一分钟,就能看到flag。

程序没有加壳,直接丢进IDA看会发现代码非常混乱,有很多未解析的代码,如果你使用PEID等工具检查了程序的话就会发现,程序使用VB编写,VB有两种编译模式,第一个叫做 P-Code(伪代码编译),另一种则是正常的本机代码编译,P-Code 模式会将代码编译为VB特有的伪代码形式,由 VB 的虚拟机运行,不巧的是,微软并没有公开这个虚拟机的信息,但是还是有逆向方法的,只不过需要注意一些细节,OD可以正常使用,但是在修改机器码的时候就需要特别注意了。通过使用VB专用的逆向工具也能得到一些有用的信息,比如使用 VBExplore 打开这个程序:
image

大致浏览各个控件,再运行程序,可以一一对应,其中还有两个计时器,不过没有代码对照,可能无法得知它们的用途。
直接祭出 OD,开始调试程序。

注意:还有一款实用软件 VB Decompiler,它可以反汇编以及反编译VB程序,对于这种P-CODE还是能够处理出一些有用的信息,但是代码比较难看,这里不以它为参考。

首先要了解逆向 VB 的一些基本技巧,由于这是一个GUI程序,所以想要定位关键代码,一定要了解一些VB的API,比如负责弹出窗口的 rtcMsgBox 或者 __vbaNew2,以及操作字符串的一些函数,这些都是破解中较为常用的,强大的 OD 已经集成了一些插件,可以让我们直接在这些系统函数中下断(打开OD后上面的灰色工具条中,点击VB):
image

这里能看到很多实用的断点工具,本题主要使用第一项(因为在播放满一分钟时会弹出一个窗口),点击后再打开断点窗口,能看到新增加了一个断点:
image

这个断点就在 rtcMsgBox 了,以后程序的运行过程中,如果再次调用到了这个函数,调试器就会断在这里,方便我们进行回溯。
然后F9运行程序,打开一个MP3文件(大于1分钟),点击播放按钮开始播放,等播放到1分钟(可以直接拖动进度条),如果不出意外 OD 会触发之前下的断点:
image

这时观察栈中的数据,根据函数调用约定,这时栈顶的内容就是调用者的地址:
image

有些情况下栈顶可能并不是调用者的地址,这时可以点击上方工具栏中的 “k” 按钮,显示调用堆栈:
image
这里也能看到调用者的信息。
双击调用者的地址,在反汇编窗口中转到关键函数,这时有两种办法,其一就是定位到函数开头(push ebp、mov ebp,esp …)下断点,然后单步弄清程序逻辑,另一种的思路是:由于我们已经找到关键函数的地址,所以可以在IDA中找到对应位置,然后尝试反编译出伪代码以减少工作量。
我们直接使用IDA载入,找到地址为 0x004044C0 的位置,在这个地址上按下 P 键,再使用 F5 就可以看到伪代码了。
函数很长,截一部分:
image

很容易就能够想到,变量 v35 所存储的应该就是已经播放的时间,依据就是代码将 v35 与 60000 以及下面的 60010 进行比较,在 VB 中,计时器有关的时间(秒数)会放大 1000 倍,这里的 60000 所对应的应该就是 60 秒了。
对照着伪代码,整理出程序的逻辑,不停地(应该是1秒一次,可以在 VBExplore 中看计时器的属性)将已经播放的时间和 60000 比较,如果小于就执行一些操作,如果大于或等于,就弹窗。
image

当时间没有超过 60 秒时,有一处判断:
image

如果运行到这里,应该就会拿到 flag 了,那么直接暴力一波,在 OD 中做如下修改:
image
改为:
image

再次运行程序(提示:可以将修改保存到程序,方便操作),当播放到1分钟时,会弹出这样的对话框:
image

音频还在继续播放,但是点击确定之后程序会退出,而且也没有 flag 出来,百度一下可以找到关于这个错误的信息,一般是控件的属性设置出错导致的,也许你想尝试捕获这个对话框,但是无论断 rtcMsgBox 还是 __vbaNew2 都没有用处,OD 没有捕获到这两个断点,仔细思考一下,对话框弹出后音频却没有间断,那么显然这个对话框控制权并不在本程序,而是在其他位置,其实,这是一个系统所抛出的异常,它位于 kernel32.dll 中,想要捕获到这个窗口,需要了解一下 windows 异常处理机制(这里不详细介绍),我们可以在系统函数 RaiseException 下断点,利用命令 bp RaiseException 即可。
image

在断点窗口中看到新的断点位于 kernel32.dll 中,下好断点 F9 开始执行程序,当播放时间满 1 分钟时,会断在这个断点,打开调用堆栈窗口,就能找到程序中调用者的信息:
image

定位到这块代码,找到了触发异常的函数 __vbaHresultCheckObj ,关于这个函数的具体信息可以在百度上找到,它的用途是检查某个对象(应该是VB的特有函数?),我们之前的修改可能造成了某个对象的属性出错,使得这个函数不能正常工作,但是这个函数上方正好有一处跳转:
image

可以将它改为无条件跳转(原来为 大于或等于 则跳转): jmp short 004046BF
然后将修改保存到文件,再次运行:
image

顺利拿到 flag : LIstenCare

05 Replace

第五题是一道经典的 输入-验证 类型题目,打开程序,要求输入一些内容,然后进行 check,随便输入一些内容(输入的时候发现,只能输入数字):
image
程序直接崩溃了,这个验证的过程应该不会很简单,我们直接使用IDA打开程序,通过搜索字符串的方式定位关键函数,直接定位到了函数 DialogFunc,反编译后查看伪代码:
image

代码比较奇怪,反编译的似乎不太正确,很多函数无法反编译,而且 IDA 也提示我们输出的结果可能是错误的,静态分析暂时没有什么好办法,那么打开 OD 尝试动态分析。
依旧是先在关键函数下断点(我们在 GetDlgItemInt 上面下断),然后 F9 运行程序,在随意输入一些数字后,点击check按钮,程序触发断点:
image

步过这个系统函数之后发现 EAX 中存储的值为我们输入数字的十六进制,例如输入 12345,EAX中的值就是 0x3039。

单步程序,当单步跟踪到这里:
image

有一句奇怪的指令 db 81 ,查询 INTEL 手册并没有发现 0x81 对应着什么指令,猜测这个字节是多余的,右键这句代码 –> 分析 –> 从模块删除分析:
image

代码就会变成这样,看上去比原来好一些(下面的 pushad 以及 popad 相当于没有执行任何操作):
image

通过单步整理逻辑,0x4084D0 中存储的是我们输入的数字 + 2,这里再加上 0x601605C7 ,继续单步,又加了2,那么最后 0x4084D0 中所存储的就是 输入 + 4 + 0x601605C7
随后程序执行到了这里:
image

两条 JMP ,紧跟的就是字符串 correct ,这种情况下,如果没有另一处跳转能够直接转到 0x401073 的话,是永远不可能出现 correct 提示的,接着单步程序,来到这段代码:
image

动态在 0x40466F 生成了一条代码,并将执行流切换到那里(期间还会对 0x4084D0 进行几次自增,但是在自增前已经将其中的值取出到 EAX 中了,所以并不干扰计算)。
image

将 0x90 赋值给 EAX 对应的地址,而此时 EAX 中的值就是上面经过处理的输入,根据 INTEL 手册,0X90 所对应的指令为 nop ,思路比较明显,如果能使这里的 EAX 的值为 0x401071 ,那么就能将那两条 JMP 中的第二条去掉,从而使程序输出 correct。
不过我们的输入会经过加法处理,经过处理的数据已经很大了,并不能达到目标地址,这里利用整数溢出,输入一个很大的整数,使执行加法的时候产生溢出,达到理想的地址。
于是我们需要满足算式: input + 0x601605C7 + 4 = 0x401071
使用计算器计算:
image

由于是 INT 型数据,所以只取后4个字节 即 0xA02A0AA6,转换成十进制就是 2687109798,输入程序:
image

flag:2687109798

  • Title: Reversing.kr 4 5
  • Author: Catalpa
  • Created at : 2018-09-04 00:00:00
  • Updated at : 2024-10-17 08:53:47
  • Link: https://wzt.ac.cn/2018/09/04/reversingkr4-5/
  • License: This work is licensed under CC BY-SA 4.0.
On this page
Reversing.kr 4 5