首页
社区
课程
招聘
[原创]看雪CTF.TSRC 2018 团队赛 第六题 追凶者也
发表于: 2018-12-11 23:12 2634

[原创]看雪CTF.TSRC 2018 团队赛 第六题 追凶者也

2018-12-11 23:12
2634

先试运行了下,果然win10运行不正常,没有退出,CPU立马上来了。

拖进ida,ida自动定位到了WinMain函数。但是,函数只调用了一个空函数。

事出反常必有妖。因为用户函数比较少,很容易就发现程序使用的tls回调函数,从exports中亦能看出。查看回调函数,其中有两个调用,和一个线程函数。

先看smc函数,明显是修改sub_401280偏移4字节处的5个字节数据,第一个字节修改为E9,对应jmp指令,后面4字节数据当然是跳转偏移,所以是跳到off_414014指向的函数处。

顺着往下走,看看主函数到底执行了什么。原来指定了窗口的消息回调函数DialogFunc,ID为1002的控件被点击时的响应函数为sub_401040

sub_401040除了获取了文本框的输入,最后出了个弹窗,似乎什么都没做。此条线就到此为止了。回到tls回调函数,还有一个函数调用的一个线程函数没有分析。go on,看hook_GetDlgItemTextA函数。

先是通过get_api_GetDlgItemTextA函数获取GetDlgItemTextA的地址,然后修改GetDlgItemTextA函数偏移32字节处的5字节数据。与上次的smc类似,第一个字节修改为E9,后4字节为偏移,是jmpsub_401A10的偏移。下面列出了GetDlgItemTextA的代码,就是将754A6B56处本来要跳到返回的代码改成了跳到sub_401A10,也就是hook了GetDlgItemTextA的返回。

再顺着往下走,看sub_401A10

咋一看,有点费事,动态跟下就出来了。基本过程是:

所以检验点就出来了。
那线程函数是干嘛用的呢?

原来是为了下次按键点击时作准备,继续hookGetDlgItemTextA

这里的校验有两个,下面的hash函数其实在取api的时候用过,按道理讲是不可逆的,应该实际上的check只有一个,第一个满足条件了,第二个也应该就满足了。其实还有个隐含条件,就是输入应该是小于20字节的,可以从取输入的地方可以看出来,那第二个条件也可以说是防止多解。看go_check

go_check函数先初始化了一个33的全局数组,再进入check函数。check先检查输入长度为偶数,再以2字节步长遍历输入,进入move对33全局数组进行操作,最后检查全局数组值为1-8,最后为0。

细看move函数,以遍历的输入2字节的第1字节为控制方向,第2字节为控制对象,进行上下左右的移动,原位置0。仔细一想,这不就是拼图游戏,0为空位,考虑到输入长度的隐含限制,应该是最少步数完成结果,具体步骤如下:

所以最终flag为:d6d8s7s4a1w2a5w6
输入试试,果然成功。

我十分好奇,为什么在win10上不能运行。原来秘密藏在api的获取过程中,代码如下,将就用伪代码看看吧。

先取dll基址,具体实现是:通过PEB找到PEB_LDR_DATA指针,再找到InInitializationOrderModuleList双向链表,遍历dll的全路径名称,进行hash计算与预设hash值比对。这里问题就来了,win10和win7 64位环境中user32.dll的全路径名称并不一致,就算基本路径一致,大小写也不一样。程序中预设的全路径名称为C:\Windows\syswow64\USER32.dll,所以即使是在win7 32位系统中也是运行不正常的,会一直遍历双向链表。要想通用,只能取BaseDllName,并且hash前统一大小写。

 

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//