入手
驰那边安装讯飞输入法后,他将全部文件打包发送过来。解压后发现有.exe
和.dll
文件:
所以要检查的目标,就是这些二进制文件。
根据旭抓包的结果,日志请求会访问 /log.aspx?c=1002&v=2.0&t=20170613144351
这样的地址,所以,最基本的就是在全部二进制文件中搜索字符串&t=
。搜索确认后,发现在文件BlcCore.dll中存在这条格式化字符串。
而查找这条字符串的交叉引用,发现只被blc::WebEngine::start(int **this, char *a2)
调用:
所以,这个函数就是我们接下来主要分析的目标。
时间戳
上文提到的格式化字符串,出现在这里的sprintf()
调用:
因为我们从http请求,知道t
的值是时间戳,所以sprintf()
的最后一个参数应该就是字符串20170613144351
。
Buf结构体
反推时间戳的来源,发现是从一个自定义的结构体中得来的。而这个结构体是从方法blc::WebEngine::getCurDate()
得到的:
这个结构体实现了动态buf管理,应该类似于C++中的std::string
,结合经验和具体的代码,在IDA中新建一个对应的结构体类型Bufstruct
:
并将一些类似的变量类型都修改为Bufstruct
http请求body
继续检查函数blc::WebEngine::start(int **this, char *a2)
,发现在下方有调用blc::HttpEngine::setRequestBody()
,这个方法的第一个参数是this
指针,第二个是char *
,第三个是unsigned int
:
所以可猜测,第二个参数是请求body的内容,第三个参数是请求body的长度:
而这里反推v5
的来源,可以确定这是一个大小为8 bytes的结构体,保存了body的指针和长度:
函数sub_100067E0()
就是生成这个结构的方法,可以再次确认这个结构保存的是长度和指针:
于是,我们接下来就只需要检查在调用setRequestBody()
之前,对请求body结构体进行了哪些操作。
找到xor
在调用setRequestBody()
之前,发现请求body的内容有被进行了一个xor操作:
由此可知,这里生成了某个xor密钥,以Bufstruct
结构形式保存,并且将其与请求body做了正好一次异或加密(无循环)。所以,接下来就只需要确定这个xorKey
是如何生成的
找到xor密钥生成方法
向上查找调用情况,发现xor密钥是通过某个拼接函数将两个Bufstruct
拼接得到的:
这个拼接函数的实现如下:
具体跟进函数appendBufstruct()
,确认其是将第一个buf附加到第二个buf的后面:
再根据这个方法调用的具体参数,可知xorKey
是将请求body的长度附加到了时间戳的后面
总结
由以上逆向分析可知,上传请求时,其query中的时间戳和请求Body的长度会拼接到一起,得到一个xor密钥。随后对请求body的起始部分,做一次异或加密,将结果作为最终的请求Body。所以,在实际逆向时,可构造同样的密钥,再次异或解密。解密的结果,就会很容易分析出来是gzip压缩包了。