背景
最近在群里看见一张二维码,刚点开图片还没扫码,微信app就崩溃退出了。这引发了我浓厚的兴趣:崩溃退出多半是存在内存错误,如果能在二维码里编码特定的数据,产生可控的越界读写的话,说不定有利用价值。
从微信入手
先看看微信的报错信息:
非常清晰明了,是在libwechatQrMod.so中产生了一个对空指针的解引用造成的崩溃,并且还附上了出错的地址,可以直接在ida中定位相关代码:
正是这一句memcpy出了问题。但是native代码读起来太麻烦了,并且涉及大量数据格式的处理,没有符号表非常难读,于是转变思路。
其他的qrcode库
已知微信识别不了,如果其他库也无法识别,很可能就是二维码库本身的问题。
我先后尝试了多个在线解析二维码的网站,也用python的zbar和opencv尝试识别,都无法从中读取任何信息。那么很可能这个漏洞就是格式解析错误导致的了,但是仅从二维码本身又看不出问题,事情陷入僵局。
开偷
不过就在这时,群里转了另一篇文章,里面附上了生成这种畸形二维码的代码:
1 | import qrcode |
可以看出,问题的关键在于代码在填满qrcode的数据区之后又添加了一个空的QRData,但是又重载了put方法使其长度被写为1,导致解析器认为后续还存在数据段,从而产生越界读。
后续
为了研究这一漏洞是否具有利用价值,我又去读了一下qrcode具体的编码过程。
数据与纠错码会以上图的顺序进行填充,加上掩码和版本信息。数据段后续具体存放的是什么数据依赖于具体的实现,但是并不能像设想的一样将自定义的数据写入任意地址,所以大概也没什么用。
漏洞修复
这篇文章刚写一半,就发现opencv已经把这个漏洞修了,出问题的代码如下:
1 | - count = (available + 7 / 8); |
非常明显的低级错误,可惜不是自己发现的。水平还有待提高。
参考材料
https://t.me/TimeAxis/892
https://nano.ac/posts/86257129/
https://zhuanlan.zhihu.com/p/85224424