这道题通过HOOK来隐藏程序逻辑,而HOOK是在Tls回调中做的,知道Tls回调就能够发现猫腻了。
拿到题后发现是窗口程序,就打开ida找创建窗口的代码,从而找到窗口过程函数。结果发现WinMain中啥也没干:
于是赶紧检查WinMain之前可能执行的代码:1.调用全局对象构造的__initterm
函数(未发现作者代码) 2.TLS回调(若注册了TLS回调,在IDA Exports窗口中可以看到,果然有猫腻):
查看函数sub_401D50的代码(直接看手动重命名后的代码):
第11行是在计算函数401120距离函数401280+9的距离:
之后便将计算的距离FFFFFF97
保存在变量v3中,将v3和v2拼起来的按照字节序放在一起为:E9 97 FF FF FF
(明显是条JMP指令啊)
第12行则修改函数401280的代码内存为可读写
接下来的循环将字节序排列的E9 97 FF FF FF
写到函数401280+4
的位置
很明显可以看出这是一个HOOK操作,可以通过IDA HEX View直接将401284位置的数据改为E9 97 FF FF FF
看一下HOOK的目的是什么:
原来是在这里跳转到了函数401220去执行了,而被HOOK的函数401280就是在WinMain里调用的函数,看下函数401280的功能——创建Dialog窗口:
至此创建的窗口找到了,窗口过程也找到了,迫不及待去瞄一眼:
sub_401020中也啥都没有做,就不截图了
直觉告诉我这里还是有有猫腻,于是回到TlsCallback_0中继续往下看,看函数sub_401C10中做了什么:
和上一个HOOK的操作很相似,这里HOOK的是GetDlgItemTextA+0x20位置的代码跳转到00401A10(刚好是GetDlgItemTextA函数获取用户输入后的位置!)并且将原位置的代码保存到了全局地址004147DC
的位置:
那00401A10
位置的代码肯定就是真正的验证代码了(具体流程看代码注释吧):
校验1:函数00401290:
发现全局数组4047D0的初始数据为:4 1 3 7 2 5 8 6 0
,经过函数401380的变换后数据成为:1 2 3 4 5 6 7 8 0
则通过校验
并且根据for循环中的判断我们发现输入的偶数位只能是w d s a
中的的一个,这不就是方向嘛!
再看看函数401380的第二个参数为输入的奇数位内容减'0',一般字符数字转为int数字会有这样的操作,所以可以判断key的规律就是方向+数字...代表那个数字向哪个方向移动
此时找到了规律就懒得分析函数401380的逻辑了,直接从数字4 1 3 7 2 5 8 6 0
上找找突破:
排列一下:
这不就是一个数字拼图游戏嘛,0附近的数字可以和0交换位置:
玩儿一把游戏,走出最短移动路线:
在验证了最短路线就是key之后,校验2的目的也明确了:限制最短路径。
验证成功后就将MessageBox的标题改为OK!
内容改为success'
,恢复GetDlgItemTextA
被HOOK的代码并调回去执行,执行完之后回到窗口回调中“假装”验证一下,便弹出MessageBox。
最后再把TlsCallback_0中创建的线程看一下:
原来是根据全局标志位4147F在GetDlgItemTextA
被HOOK的代码恢复后重新HOOK
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2018-12-21 12:48
被KevinsBobo编辑
,原因: