最近整了个 R86S 之后又开始折腾起了 IPTV。几年前曾简单抓包获取了一堆播放地址,现在已经不能用了。尝试重新使用 wireshark 抓包,以为拿些比较稳定的 IGMP 组播地址,但是发现广东电信已经不会组播地址了,尝试使用网上的组播地址也都不能用了,可能是我配置不对,或者使用 DHCP 形式连接盒子不会下发 IGMP 地址,又或者电信现在已经不下发组播了。那就只能退而求其次使用 RTSP 地址了。但是我发现抓包获取的 RTSP 地址都有一个小尾巴包含了 IPTV 账户的登录信息,并且删掉之后就不能播放了。那这些播放地址都不是永久有效的,需要定期刷新,所以只能去研究一下自动化提取了。
首先先破解盒子,获取 ADB,然后就能提取 /system/app/
里面的 APK 了。一股脑全部丢 jadx 中。然后找到类 com.gd.chinatelecom.iptv.openapi.internalApi.impl.IPTVApiImpl
,其中的 authorize 就是我们需要的验证过程了。(这个类是通过搜索 AuthenticationURL
字符串找到的,很轻松)。
通过分析代码,发现验证过程如下:
http://eds.iptv.gd.cn:8082/EDS/jsp/AuthenticationURL?Action=Login&return_type=1&UserID={userid}
。其中 {userid} 是 IPTV 的账号,不包含 @ 和后面的东西。这个链接会返回一个 epgurl
,拿出其中的域名,这个才是真正的验证服务器(电信这相当于手动实现了一个负载均衡啊。。。)base_url
然后 GET 请求 http://{base_url}/EPG/oauth/v2/authorize?response_type=EncryToken&client_id=smcphone&UserID={userid}
,返回一个 JSON,获取其中的 EncryToken
。{randint(0, 1E7)}${token}${userid}${IMEI}${IP}${MAC}$$CTC
的 DES3 结果,记得 pad 一下。randint(0, 1E7)
就是 0 到 1e7 的随机整数;token
是上一步获取的;userid
是 IPTV 的用户名;IMEI
是盒子的 IMEI,可以为空;IP
是盒子的 IP,可以任填,我用 127.0.0.1
都行;MAC
是盒子的 MAC 地址,这个是写在盒子上的,不可以任填,格式是 AA:BB:CC:DD:EE:FF
。authinfo
之后,GET 请求 http://{base_url}/EPG/oauth/v2/token?client_id=smcphone&DeviceType=deviceType&UserID={userid}&DeviceVersion=deviceVersion&userdomain=2&datadomain=3&accountType=1authinfo={authinfo}&grant_type=EncryToken
,然后得到 cookie。有了上一步获取的 cookie 之后,直接 GET 请求 http://{base_url}/EPG/jsp/getchannellistHWCTC.jsp
就能获取所有频道列表,提取 RTSP 也很简单了,这里不再赘述。