逆向一款恶意Eclipse插件的经历
引言
首先,我想要说明的是,我不是一个安全研究员、白帽子或者逆向工程方面的专家。我目前正在从事Java开发,但一直对信息安全感兴趣。
最近我对信息安全的诸多领域进行了研究,包括二进制、逆向工程到破解WPA。因此,我决定搭建一个信息安全学习博客,用于记录学到的知识。即便没有人读我的博客(译者:事实上还有个小可爱翻译成了中文),至少我能够记录下自己的收获,而且我发现把知识和经历写下来能够让我对知识有更深刻的认识。
寻找目标
今天我有相当多的空闲时间,所以我决定用逆向工程来试手。我具有多年的Java编程经验,而Java反编译器通常可以为我提供确切的源代码,因此对我来说逆向Java项目是个不错的选择。
当我正在考虑逆向哪个项目的时候,我想到之前看到的一条Eclipse插件的评价。在看到这条评价后,我决定停止使用这款插件。
这相当值得怀疑,我并不认为这款Eclipse插件需要具备这个功能。
请注意,这个插件上榜了Java Eclipse Plugin Top 20,并有将近400k的下载量。
调查
我首先需要得到这个插件的副本,然后反编译它,或找到项目的源代码。
我第一个检查的地方是项目网站,它引导我前往项目的Github页面。我看过Github上的代码,但并没有找到所说的“phone home”的功能。也许我错过了一些东西,但是我怀疑开发者隐藏了相关的代码。所以我决定安装这个插件,然后反编译它的二进制文件。
这个插件可能会对我的电脑产生危害,所以我在VirtualBox上安装了Windows虚拟机,并在虚拟机内部安装了Java和Eclipse。
接着我安装了该插件,通过研究了Eclipse插件二进制文件的存放位置,最后在<user_home>/.p2/pool/plugins
文件夹找到了它们。
我把这些jar包从虚拟机复制到我主机的Eclipse里,使用了一个(我认为是)值得信赖的反编译器——jd,来分析这些类。打开主要的类文件以后,我马上发现了一些有趣的代码,这些代码用来存储在一个名为adclick.count
的变量。
值得注意的是,该代码并没有出现在插件的Github版本中。
我很快发现这个二进制文件包含了相当多的类,与其一个个检查它们(可能需要几个小时),根据Eclipse Marketplace上的评论,该插件产生了一些HTTP连接,所以我决定反编译所有调用java.net.*
包的源代码。
现在我缩小了需要检查的代码的范围,这样就能更深入地看看这些代码。
检查这些类时,我在IOUtils
中发现了一些可疑的代码,它似乎提供了一个关闭HTTP连接的Helper Method(为什么代码反编译器需要关闭HTTP连接?)。
接下来,我在UIUtil
类中发现一个方法用来在外部浏览器中打开URL,并增加adclick.count
变量。
在UserUtil
类中,我发现有一点值得关注——collectUserIp()
方法中调用了多个(看似不相关)的各种网站。
我跟踪了这个方法,看看这些代码对用户信息做了什么…然后发现它被用在BackgroundHandler
类中。
检查这个类后,我发现该代码收集了用户系统的大量信息,将其转换为JSON对象,然后将其发送到http://decompiler.cpupk.com/statistics.php”
。
现在,我想看看插件收集并发送了哪些的信息到他的服务器上。我在主机上安装了Burp Suite,开启HTTP代理,这会让虚拟机中的流量通过这个代理转发。
然后在虚拟机中设置系统代理。
我再次启动Eclipse,并检查通过代理发送的请求和响应。首先产生了一些来自Eclipse的调用,但是我很快收到了来自thecollectUserIp()
方法的调用。pv.sohu.com/cityjson
返回的是一个JavaScript变量,其中包含了调用者的IP、所在大陆的id和名称
。
接下来我观察了对ip.taobao.com/service/ipinfo.php
的调用,它则返回了更多关于用户IP的地理信息。
最后我观察到了Eclipse Marketplace上的评论所描述的“call home”功能。它将用这些信息生成JSON对象并将其发送到decompiler.cpupk.com/statistics.php
。
把注意力转回analyzeUserInfo()
类,调用上传用户信息的这个方法实际上必须有一个重要的服务器响应,而这个响应是通过其他更多的方法来处理的。
这时候我找到了checkAdConfig()
方法。checkAdConfig()
方法解析了JSON对象的诸多属性,比如adConfig
,adCondition
,adStyles
等等。
根据BurpSuite显示的服务器响应,当前并没有提供其所需的所有变量。
因此我决定在代码中搜索之前注意到的adclick.count
变量。这一次我发现了一个新的类——HtmlLinkTrimItem
。
这个类实现了一些值得琢磨的功能。首先,它实现了一个内部浏览器。其次,它在初始化时调用一个updateTrimUrl()
方法,该方法在单独的线程中使用了隐藏的浏览器,并调用了由trayLinkUrl
定义的URL。
我在代码中搜索了对HtmlLinkTrimItem
类的引用,发现作者在多处引用了HtmlLinkTrimItem
类。
LinkTrimChecker
类使用了TrayLinkV1
类和TrayLinkV2
类,用于实例化HtmlLinkTrimItem
(由此反过来触发后台浏览器)。
TrayLinkUtil.displayTrayLink()
方法又调用了LinkTrimChecker.displayTrayLink()
方法,然后被使用在BackgroundHandler.checkTrayLink()
方法中。
如果你前面有仔细阅读,那么你可能已经注意到checkTrayLink
方法正是处理服务器返回的JSON对象的方法之一。当响应中有trayLink
时,TrayLinkUtil.displayTrayLink
就会被调用。
BurpSuite上的记录表明这个对象存在,但它是空白的。
所以如果trayLink
不是空白的话会发生什么?
如前面讨论的那样,程序将调用displayTrayLink()
方法,它将委派给LinkTrimChecker
处理。
但是你可能会注意到displayTrayLink()
方法的第二个参数TrayLinkUtil.enableShowTrayLink()
,很显然只有在解析为true
时,才能启用后台浏览器。enableShowTrayLink()
方法会检查首选项中包含了trayLinkStrategy
,然后UserUtil
类中的matchAdCondition
方法才会返回true
。
根据我之前的研究,trayLinkStrategy
是在从服务器返回的JSON对象中解析trayLink
时设置的。
接下来我又看了一下matchAdCondition()
方法。该方法检查首选项中是否包含adCondition
(或默认为100),并将用户反编译类的总数与此值进行比较,如果用户反编译类的总数超过此数字,则返回true
。
因此,在用户对超过100个类进行了反编译后,或者服务器返回的adCondition字段更改为小于用户反编译类计数的值时,则后台浏览器将开始发出请求。
接下来我要看看trayLinkUrl
是如何被设置的,这是后台浏览器所要打开的URL。我在TrayLinkUtil
类中发现了用于设置trayLinkUrl
的代码。首先根据服务器返回值设置trayLinkStrategy
属性,然后第二种方法检查属性,如果它包含一个具有url字段的JSON对象,则返回此URL。否则,它则为包含这些对象及其权重的数组,程序将根据权重随机选择URL。
我同时注意到后台浏览器是在一个定时器上打开的,这个定时器再次由TrayLinkUtil
类中的getTrayUrlDisplayTime
方法定义。该方法表明trayLinkStrategy
还包含了showTime
属性以及前面发现的URL。
我决定结合发现到的所有内容,使用BurpSuite修改服务器响应来触发广告软件功能。我修改了服务器返回的trayLink
,使其包含URL到google.com
,并将showTime
改为1分钟。我还将adCondition
属性改为2,毫无疑问,我现在反编译类的数目已经超出了这个限制。
我使用jvisualvm来Hook Eclipse,并查看HeapDump,以确认我已经修改了相关属性。我在HeapDump上运行了以下查询语句(OQL)。
select s from java.lang.String s where s.toString().equals(“trayLinkStrategy”)
结果显示有两条记录,第一条为Eclipse InstanceProperties
进行的引用,由此我观察到了之前进行的修改。
值得注意的是,键值表的第3和第8项分别包含trayLinkStrategy
和adCondition
。现在设置添加的JSON对象,并将adCondition
的值改为2
。
大约一分钟之后,我注意到BurpSuite有了动静,如图所示,虚拟机已经向google:80发送了一个请求。成功了!
为了确保这不是一个意外(因为可能很多不同的应用程序/代码向Google发送请求),我重复测试了imgur.com 。
结果是一样的,虚拟机向imgur.com:80发出请求。
此时虚拟机弹出了IE证书的问题。这可能是由于imgur通过TLS请求资源,但BurpSuite的证书不符合这些资源的DN(身份识别信息?)。
当离开Eclipse窗口,可以在BurpSuite看到imgur的调用流。
结论
很高兴我对该插件进行的研究产生了一定的成果,我揭露了一个上榜Java Eclipse Plugin Top 20的插件内存在的恶意代码,以及分析了Eclipse Marketplace评论所说的“call home”方法。我认为这个功能的代码没有出现在Github版本的代码中就足以证明它可能不怀好意。
我想要补充的是,尽管这个功能存在,但我并没有观察到服务器提供了所需的JSON对象来触发广告。
我将就该问题联系Eclipse官方,他们不会容忍这种功能。
如果有任何问题,请随时发表评论。
Append:基于进一步的研究,这些恶意代码可能被用于下载文件到用户系统上(仍然要更深入的测试)。因为通信是完全未加密的,所以可能会产生非常恶劣的影响。
Append 2:我对上述猜想进行了测试。
我伪造了一个只包含一个带消息的JFrame的jar文件,并用python开放在80端口
sudo python3 -m http.server 80
然后我将主机IP地址设置为trayLink
时,虚拟机中显示了以下内容。
我虽然不认为会有人打开或保存这个特定的文件,但可能存在另一个漏洞,在不必点击任何东西的情况下就会对操作系统产生危害,或运用社会工程学,例如,如果弹出窗口设置为EclipseUpdate.exe,那么可能就会有一些人上当了?
由于“call home”基于HTTP,因此也可以通过修改MITM来攻击受害者。
Append 3:Eclipse已经从市场上移除了该插件,并发布了相关通告,建议用户卸载该插件。
译者注
这篇文章是在cos的分享里看到的,因为英文不是很难,所以就花了点时间翻译成了中文,这篇文章同时也发表在我的博客上。
*参考来源:Reverse Engineering an Eclipse Plugin,作者:Pythong_song,已于作者取得联系,并获得翻译授权。转载请注明来自 FreeBuf.COM