伪造掌阅ireader plus升级的服务器

1. Introduction

最近把原来的499 kindle卖掉了,换成了国内掌阅出的ireader plus(999),掌阅的性价比的确高一点,比(800)kwp3配置看起来高了一些。然而书城资源上,kindle的生态比掌阅好了很多。 我的主要阅读是非休闲的书籍,而且专业书籍一般也不从kindle上买,所以ireader plus更适合我的情况。 但是,ireaderp官方没有放出附件包,提供的服务也不能和kindle比,比如邮件推送,比如公众号推送等等。 了解到ireader是基于android 4.4进行“深度定制”的,但是和pc在相连的时候,是通过MTP协议,而且默认是关闭了usb调试的,万能的国民发现在开机时候,某个时刻点击右上角会弹出android系统自己的设置,并开启usb调试,这样,就可以通过adb连接pc。 但是点击的时机把握太重要了,我点了好多好多次,只点出来一次。 开启usb调试以后,就可以通过adb安装apk,ireader的一个破解群,也提供了一个桌面apk和切换桌面的epub文档。而我唯一点出的一次,竟然鬼使神差在系统设置里把桌面设置成了掌阅默认的。也就没法切换了。 于是想通过别的方法来开启。

2. 开启usb调试的探索

探索1

通过MTP挂载的文件里,发现有个jar包,从文件夹路径以及名字上判断是蓝牙语音读书的插件包。然而反编译以后,并没有发现可以利用的点。

探索2

尽管没有开放出固件,但是万能的国民开启了usb调试以后,就可以获取到ota包。 同时在mtp挂载里,查看ota_log文件,发现ota包存放的位置是/storage/emulated/0/adupsfota/update.zip,在群里问侃侃,说mtp挂载的应该是/storage/emulated/0/,我尝试直接建立文件夹,并把ota包放进去,无法检测到。推测是文件夹权限的问题,但是如果的确挂载的是/storage/emulated/0/,而且之前升级时自动新建了一个adupsfota/文件夹的话,应该会冲突,不允许我建立的。这里依旧疑惑。

探索3

既然是通过ota,那么直接分析出整个ota的过程,通过伪造假的ota服务器来进行升级不就行吗,升级成自己修改过设置的包,而且我认为掌阅的开发人员在调试的时候,不会是手动找时机点右上角的设置吧。 下文皆是基于此项探索进行的。

3. 抓包

既然要探查ota过程流量,而ireaderp是通过wifi连接的,那么就需要建立热点,并抓取热点的流量进行分析。由于我的系统是debian sid(tesing),网上流传的小米wifi的驱动无法编译,linux内核太新了,提示错误code model kernel does not support PIC mode,在简单搜索以后放弃解决这个问题,直接切换到别人的win下面去。小米wifi建立热点,用wireshark神器抓包分析。

3.1 分析小米wifi的流量数据

由于自己建立的热点数据流量很少,只有13条,其中前6条是ireaderp android系统的服务行为,连接谷歌。后面才是在系统里点击更新时产生的流量。 但是很明显这里的流量都是单向的,从小米wifi(10.0.2.*)到ota服务器(43.254.53.99)。而且三步握手数据也不全面,但是可以看到有个HTTP响应数据,点开数据查看,会发现响应的内容如下:

{"flag":{"LUrl":"no","isInner":1,"isupgrade":1,"displayApp":0,"rand":"611708206","updateStep":0,"DUrl":"http://fotadown.mayitek.com/ota/","mid":"20161129160819WF8361","connfreq":"2940"},"status":1010}

而之前在探索1中,找可用的数据时,system/build.prop文件里有很多有用的信息,比如版本号等等。跟这里的信息一联系,有很多可圈可点之处。而且很明显http://fotadown.mayitek.com/ota/是下载ota包的连接。

3.2 分析pc上网卡的数据

小米wifi最后也是通过本机的有线网卡进行的数据转发,因此抓包本机的eth网卡。 通过筛选命令ip.src==43.254.52.99 or ip.dst==43.254.52.99可以获取到整个交互过程。同样数据不多,可以看到一条重要的HTTP POST数据,

POST /ota/detectdown/detectSchedule.do HTTP/1.1

Bingo!这就是检测版本号的链接。 在随后的一条就是咱们上面获取到的响应数据。 同时通过dns筛选到底ireaderp是访问什么网址进行请求ota版本检查的,发现了fota4.adups.cn,(实际上是访问的fota4.mayitek.com,只不过被重定向了) 那么接下来只需要伪造服务器就可以了。

4. 伪造服务器

分析下整个访问的流程: ireaderp(发送网址fota4.mayitek.com请求) -->小米wifi(转发这个请求) -->dns服务器(解析出域名的ip返回给)-->小米wifi和ota服务器进行三次握手建立链接(将请求的网址发给ota服务器)-->ota服务器(响应这个请求)-->小米wifi(转发返回的数据)-->ireaderp(自己的程序处理响应数据)

这是我大概分析的流程,我们只需要在dns服务器这里,欺骗ireaderp即可。

4.1 dnsmasq

这个软件是很轻巧而且傻瓜式的配置,既可以作为dhcp的分发,也可以进行简单的dns服务。然而实际上最终我被它整乱了,放弃了使用。 本来我在本地pc的/etc/hosts里映射了那两个域名到本机,但是在测试过程中发现,dnsmasq不稳定,在其日志里,一会儿优先解析hosts文件,一会儿又通过正常的dns服务器解析。 不再赘述了(这句话饱含心酸)。

4.2 Bind9

放弃dnsmasq之后,搜索搭建dns服务器,发现主要是关于bind9配置的,便学习了简单的配置方法。 不贴说明介绍了,先贴下配置的地方吧。bind的主目录是/etc/bind/,编辑named.conf.local文件,添加两个zones:

zone "adups.cn"  { type master; file "/etc/bind/db.adups.cn"; };
zone "mayitek.com"  { type master; file "/etc/bind/db.mayitek.com"; };

然后对照里面的file新建两个文件,直接cp db.local db.adups.cn用local模板建立即可。以mayitek.com为例,修改db.mayitek.com内容如下:

;
; BIND data file for local loopback interface
;
$TTL    604800
@   IN  SOA mayitek.com. root.mayitek.com. (
                  2     ; Serial
             604800     ; Refresh
              86400     ; Retry
            2419200     ; Expire
             604800 )   ; Negative Cache TTL
;
@   IN  NS  mayitek.com.    
@   IN  A   127.0.0.1
*   IN  A   你的dns服务器ip
fota4   IN  A   你的dns服务器ip

修改的地方可以对照着db.local来看。我的bind9版本是VERSION=9.10.3-P4-Debiansudo service bind9 restart来重启服务。

4.3 修改dns配置

修改本机的/etc/resolv.conf,添加你的dns服务器ip,注意这个文件是自动生成的,你做的修改在重启网络以后就会丢失。 尝试ping fota4.mayitek.com看看是不是你设置的dns服务器ip。如果不是,尝试修改你的dns服务器上的/etc/hosts文件映射域名到你的ota服务器ip。 用你的手机或者ireaderp测试,先记录下连接的wifi分配的ip,然后忘记这个网络,重新连接,设置静态地址,将dns服务器修改掉,连接以后,尝试去系统设置里更新。

5. 伪造服务器响应

搭建好了dns服务器以后,还需要搭建ota服务器,当然这两个可以是一个。由于我手头数据不多,只有上面那一个请求响应,所以只能先伪造上面那一个。 用python的tornado web框架写了简单的代码fake_server.py来伪造响应:

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define, options
define("port", default=80, help="run on the given port", type=int)

class IndexHandler2(tornado.web.RequestHandler):
    def get(self):
        greeting = self.get_argument('greeting', 'Hello')
        self.write(greeting + ', friendly user!')
    def post(self):
        self.write('{"flag":{"LUrl":"no","isInner":1,"isupgrade":1,"displayApp":0,"rand":"18388636","updateStep":0,"DUrl":"http://fotadown.mayitek.com/ota/","mid":"20161203160819WF9362","connfreq":"2990"},"status":1011}\n')
        print("get one");
if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(handlers=[(r"/ota/detectdown/detectSchedule.do", IndexHandler)])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

由于默认是绑定80端口需要sudo,sudo python3 fake_server.py。设置好ireaderp的dns网络配置以后,点击系统更新,会发现后台获取到了这次请求,(里面有一些杂乱的请求,不是ireaderp发出的)

6. 修改ota包

修改ota包其实是中午做的,现在还存在问题,尝试伪造update.zip包不成功,解压查看的时候,我只发现了一个md5sum的校验文件,后来改完了配置,我也重新生成了md5sum,发送给别人测试(我的依旧没有开启usb调试),更新失败。这个问题尚未明朗。

目前想法,通过修改build.prop,添加如下内容来自动开启usb调试。

persist.servICe.adb.enable=1
persist.sys.usb.config=adb

然后使用abootimg进行了打包,参考[android]system.img文件的打包和解包

7. 总结

整个过程,复习了我很多网络的知识,以及工具的使用。但是实在是太累了。从早上9.00在群里开始讨论这件事情,中午外卖,在宿舍一直坐到晚上6.00,然后去实验室继续做,最后总结文章,写到了第二天的0:30。只因为早上的讨论勾起了我的兴趣。

Reference

有大神破解了iReader plus Wireshark基本介绍和学习TCP三次握手 烂泥:dnsmasq搭建简易DNS服务器 Ubuntu Bind9泛域名解析配置 DNS开源服务器BIND最小配置详解 [android]system.img文件的打包和解包 其实还有很多很多很多参考,但是实在浏览记录太多了,没有及时mark。


文章版权归 FindHao 所有丨本站默认采用CC-BY-NC-SA 4.0协议进行授权|
转载必须包含本声明,并以超链接形式注明作者 FindHao 和本文原始地址:
https://findhao.net/easycoding/1808.html

Comments