通过题目简介和下载得到的文件格式分析,该题需要对该文件进行逆向分析
查壳
逆向第一步分析文件格式,以及查看是否加壳,本例用exeinfoPE进行以上操作
可知该程序大概率是vc6.0编译的32位程序,可以用od分析(od只能分析32位程序),并且没有加壳。
IDA静态分析
方法一:通过WinMain函数分析
用ida打开该程序
从函数名称表里能看到非常显眼的WinMain函数,熟悉windows sdk的同学肯定马上就能反应过来这是窗口程序,而不是控制台程序。
tips:其实直接打开这个程序也能看出。
附图:
一般的win32程序就是用WinMain函数作为主函数,通过操作系统调用回调函数,对用户的操作做出对应的反馈。
于是我们可以直接双击这个WinMain函数,对其进行反编译。
反编译后得到下图
再双击这个返回值(这里有点套娃的意思,return WinMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd)这个函数就是winmain函数,但是却把他写成返回值,我不知道这里是ida的问题还是别的什么问题)
发现是一个DialogBoxParamA函数,也就是对话框函数。
给出一个msdn上对DialogBoxParamA函数的解释
链接: https://learn.microsoft.com/zh-CN/windows/win32/api/winuser/nf-winuser-dialogboxparama
之前我们讲了,既然要知道我输入数值之后程序做出了什么样的反应。那就必须要找回调函数。
DialogFunc便是指向对话框过程的指针,这个对话框过程便是一个回调函数。双击这个这个函数查看他的代码
再双击这个返回值(为什么函数体就是一个孤独的返回值呢,其实这里是一个间接调用,sub_401090这个函数它其实就是DialogFunc()这个回调函数),这样就看到这个回调函数的内容了,接下来就一条代码一条代码分析咯
方法二:通过string window取巧分析
有的同学对windows sdk不熟悉,想不到WinMain函数这个切入点,那么可以抛开上面的分析思路,打开ida后快捷键shift+F12直接打开string window。
立马就能发现well done这个非常可疑的字符串。
双击这个字符串查看他在内存中的位置
双击后边的sub_401090函数,查看调用这个字符串的函数,来到汇编图形界面,按f5反编译。
这样就来到了这个关键函数(回调函数)了。
这两种方法都可以达到相同的目的。
接下来分析这个回调函数
分享一个msdn对DialogFunc的解释
链接: https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nc-winuser-dlgproc
和我们分析的函数int __stdcall sub_401090(HWND hWnd, int a2, int a3, int a4)进行比对,可知hwnd是句柄,a2便是消息,a3,a4是其他消息。
接着分析
用memset函数把string为首地址的0x104个内存空间的值都置0。
前面说了a2是消息,那么16对应的应该是WM_CLOSE这个宏定义,273对应的应该是用户按下确认键之类的吧(这里我不确定具体是什么,因为目前我对对话框过程也不是很了解,也是边学边做,说的不对的见谅)。
a3(wparam)是一个附带的消息,往往是坐标值之类的东西。
附上该函数的msdn链接: https://learn.microsoft.com/zh-CN/windows/win32/api/Winuser/nf-winuser-getdlgitemtexta
可知,该函数把输入框里的值复制到&string指向的缓冲区。
得到string的字符个数,如果大于6就结束该程序。
下面是解题的关键——v10
在回调函数的顶部我们知道了v10是一个int变量,而atoi()函数是用来将ascii(char型)转化为integer(int型)
转载一个链接链接: https://blog.csdn.net/u010806950/article/details/105505540?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166562775916782417052552%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=166562775916782417052552&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-105505540-null-null.142v53control,201v3control&utm_term=atoi&spm=1018.2226.3001.4187
可知v10的值是将string字符串 转化为int型之后加1的值
从if的判断条件可以反推,v10=atoi(&string)+1=123
,atoi(&string)=122,所以sting的值为"122xxx",即开头三个数为122,但总共有几个字符暂不可知。接下来把v12,v13,v14转化成ascii码看看
接着往下看
于是Text=“flag”,然后是置零操作
itoa()函数的功能是将integer转化为ascii,第一个参数是要转化的值,第二个参数是转化后值的储存地址,第三个数是要转化的值的进制,这里为10进制。
大家可能纳闷,v5是一个char变量,&v5是什么意思,&v5取地址,把要转化的值存到以v5为首地址的数组中,ida中将v5定义为一个char变量,但这并不代表他就是char,他有可能是char[]数组。
接下来
第一条代码使Text=“flag{”,接着第二条指令使Text=“flag{123”,到最后Text=“flag{123_Buff3r_0v3rf|0w}”
接着是一个messagebox,well done是标题,Text是内容
得到flag:flag{123_Buff3r_0v3rf|0w}
OD动态分析
但是得到了flag还不够,想知道我在文本框里输入什么值可以使程序输出messagebox。于是用od打开这个程序,定位到GetDlgItemTextA(hWnd, 1002, &String, 260);这个函数的汇编指令。该怎么做呢。
先在ida汇编图形界面中找到GetDlgItemTextA(hWnd, 1002, &String, 260);这个函数
发现了在这里
按空格进入文本界面
得到这条指令的VA(虚拟地址)为40113e
于是就定位到了这条指令的位置,在od中跳转到这个地址,并在push eax处下断点(根据右边的注释我们可以看到这里eax的值是输入框中字符串存放的首地址)
运行程序,我们之前说了sting的值为"122xxx",我们只能确定前三个数是122,后边的不确定,因此我们在输入框中输入122,接着程序运行到断点,,此时发现eax的值为19f5dc,于是在数据窗口中跳转到19f5dc这个地址
选定第一个19f5dc这个字节进行跟随
接着我们单步步过(f8),运行完40113e处的GetDlgItemTextA函数
文章来源:https://www.toymoban.com/news/detail-810578.html
发现‘31’32‘’32‘也就是122传进了19f5dc这个地址处,我们接着单步步过往下执行,运行到4011a7处
这个指令对应的就是v10== 123
我们接着往下走,运行到4011b4处
4011b4处这条指令把一个字节大小的值以补零的方式(movsx)传给eax,接着4011bb处将eax和0x78(’x‘)作比较
我们可以注意到这个字节大小的值的地址是19f5df,正好在’31‘32‘‘32’(19f5dc–19f5de)的后边一个字节,而19f5dc不正好就是输入框中字符串存放的首地址吗!于是便能联想到
这个if判断里v12,v13,v14也是文本框中输入值的一部分,那么理性推测文本框中的值也就是string=“122xyz”。那我们把这个值输到文本框里运行程序试一下
果然得到了正确答案,flag显现出来了,证明我们之前的推理正确。
最后再提一下
在ida界面中仔细观察string,v12,v13,v14的地址分别是esp+25c,esp+25f,esp+260,esp+261,会发现他们是连起来的(25ch–261h),正好6个字节,string虽然被ida判定为char类型,但不代表源代码中string便是char类型,实际上它应该是char string[6],之所以被判定为char类型,是ida的判断而已,不代表一定正确,这样就能解释的清string与v12,v13,v14之间的关系了,事实上这个小细节在reverse赛题中经常遇到,做题时多留意留意变量之间的地址关系,会有意想不到的收获。这道题就讲到这,有些地方思路比较绕弯,说的不对还请指正,谢谢。文章来源地址https://www.toymoban.com/news/detail-810578.html
到了这里,关于BUUCTF Mysterious的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!