记一次逆向某网络考试系统的经历

起因

某天c语言实验上机模拟考试,然而系统里却没有我的考试信息,万般无奈之下索性下了个wireshark抓包,结果发现这考试系统根本算不上一个真正cs结构的网络应用,服务端就是一sql server,所有的查询都是明文传输。再确定了查询考生信息的语句以后索性直接在考号填了个万能密码(‘or’a’=‘a’–),居然就进了。。。正好学校考试服务器还是公网ip,于是感觉有点搞头,回头去百度了一下客户端的安装包。准备re实战一下。

第一步 脱壳

安装好程序以后居然在安装目录里就有一个自带的UPX.exe,也不知道开发者是故意方便我脱壳还是打包程序的时候忘了删掉。。。总之直接upx -d脱掉。

第二步 尝试用IDA 看看

这看起来不大的程序居然被IDA整整分析了10分钟,小蓝三角一直跳来跳去,我以为会分析出什么,结论是这是一个VB6.0写的程序,IDA几乎没法把任何函数反编译成c
分析失败
因为vb的返回值和参数比较诡异,VB把存放返回值的地址作为参数也传给函数,并且还会把当前对象(ME也好,this也好self也罢反正是那个意思)作为默认参数也传给函数。总之用IDA看这个程序也是简直了。果断放弃。

第三步 换用VB Decompiler Pro反编译

VB Decompiler Pro反编译后的效果
果然还是对症下药效果好一些,VB Decompiler Pro在快速反编译的情况下很快就可以看到函数和对应的半VB半汇编的代码,还有关于窗体属性的设定。我本来的计划是去除登录程序中关于考号位数的限定,这样可以方便利用注入漏洞执行更多操作,但是后来发现VB对于输入框输入字符的上限也属于控件属性,应当是放进了data段,不在代码里,运行时才动态加载。但是VB Decompiler Pro不能更改控件属性,由于没有找到太多解读VB窗体属性数据的资料,我就放弃了这种思路,转而去在内存里直接找登录数据库的凭据。VB Decompiler Pro是纯静态分析工具,所以只能拿来看看,说到动调还是OD大法好!

第四步 用OllyDbg获取数据库登录凭据

我尝试直接给建立socket的API函数下断,发现没什么卵用,猜想程序应该是走了链接数据库的dll里的函数,索性直接暴力猜,一边开wireshark,一边疯狂F8,F8到有数据包就下断以后重新来过,下次停下的时候改F7就是了,一层一层拨进去,同时盯着堆栈窗口,看看有没有什么有价值的字符串,最后自然是有的,就是明文的用户名和密码。于是便拿下了数据库。

第五步 尝试解密数据库里试题的答案

数据库里面的题干虽然是明文的,但是答案却被加密了,而且虽然都是选择题,不同的题还加密了的答案还不一样。。。密文啥字符都有,不知道什么鬼。于是还是决定继续用od动调。正常人思路都会认为答案肯定是在判分的时候解密的,于是我根据VB Decompiler Pro里看到的函数名,在关于评分的函数上下断,想一点一点跟进去,结果发现这个程序会在评分是结束除了自己意外的所有程序,不得以又暴力跟进,先是patch掉数活动窗口数是否大于1的代码,又拨到一个函数参数是程序的PID,只要调用就会kill相应的程序,于是果断patch了所有对这函数的调用,总算才让OD活到了评分。
我根据密文中出现的各种字符,以为这种某种高级的base。。。于是在程序里搜索一大长串字母表一样的字符串,结果还真有,于是就下断,连带着用VB Decompiler Pro看了好半天也没看懂这是在干啥。。。
含有字母表的函数干脆还是直接一点一点动调整个评分函数。结果却发现评分的时候答案早八辈子变成了明文,也就是说答案是在开始获取试题信息的时候就被解密了。
于是又翻上去去找解密的函数

这里明显地看到加密的答案被压栈作为参数传入到函数中,这个函数调用之后堆栈中便多了“Y”或者“N”这类字样(这是判断题的答案)。
调用解密函数
解密函数用VB Decompiler Pro反编译后的结果
可以看到其中调用了00749200这个函数,还传了一个很像某种密钥的字符串进去。
解密函数中的关键操作
我发现这个函数被调用之后,内存里就出现了一个稍微正常一点的字符串。我们OD进这个函数中发现有这样一条指令。然后我们返回去看上一层解密函数,发现它只取这个稍微正常一点的字符串的第8位作为结果,说明剩下的部分都是混淆用的随机字符。
异或指令
在这里下断发现每次异或的就是传给函数的那个密钥一样的字符串的一位。
第一轮异或的结果
最后得到B
再往下F8看到还有异或,在此处下断发现这里用前面得到的B和加密了的答案异或,于是便找了个加密的答案试了一下,看到了熟悉的base64,base64解密以后正是上方那个稍微正常一点的字符串。
第二轮异或
至此才逆向出了解密答案的算法,其实还是很简单的,只是混淆太多了,容易走弯路,贴出解密用的python代码:

import base64
input=open("key.txt","r")
output=open("decoded.txt","w")
for line in input.readlines():
    line=line.strip("\r\n")
    ans=''
    for char in str(line):
        #print(char)
        ans+=chr(ord(char)^0xb)
    #print(ans)
    ans=base64.b64decode(ans).decode()
    #print(ans)
    output.write(ans[7]+'\n')
发布了11 篇原创文章 · 获赞 22 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_33917045/article/details/103782391