找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
广告投放联系QQ68610888
查看: 3006|回复: 21

[iptv信源 资源分享或寻求] 云南电信IPTV直播源(HTTP m3u8认证源)获取(技术分析)

[复制链接]
发表于 2024-1-3 18:27 | 显示全部楼层 |阅读模式
本帖最后由 op351 于 2024-1-4 14:23 编辑

1.wireshark抓包 论坛教程很多 不再赘述
2.
在抓完包以后 我们可以尝试过滤udp流量 发现没有
没错 云南电信默认不使用组播技术 而使用单播。
好处当然是机顶盒随便插哪儿都能用啦,不管你家有几级路由,只要能联网的网口,怼上机顶盒就能看。

3.
那么我们就来看看单播是如何获取的

技术实现上使用python来编写脚本

按照惯例 我们先查找CTCGetAuthInfo方法 可以发现如下请求
  1. GET /yniptv/register?UserID=xxxx&Action=Login HTTP/1.1
  2. Host: 112.115.0.132:11888
  3. Accept-Encoding: deflate, gzip
  4. Connection: Keep-Alive
  5. Proxy-Connection: Keep-Alive
  6. Accept-Language: zh-CN,en-US;q=0.8
  7. User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.0 (KHTML, like Gecko)
  8. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

  9. HTTP/1.1 200
  10. Server: nginx
  11. Date:
  12. Content-Type: text/html;charset=UTF-8
  13. Content-Length: xxx
  14. Connection: keep-alive
  15. Set-Cookie: JSESSIONID=xxxx; Path=/yniptv; HttpOnly

  16. <html> <head><script language='javascript'>function DoAuth(){document.authform.Authenticator.value=Authentication.CTCGetAuthInfo('xxxxxxxxx');document.authform.submit();}
复制代码
那么在yniptv/register中我们就获取到了CTCGetAuthInfo的值
对应的py代码如下
  1. url = "http://112.115.0.132:11888/yniptv/register?UserID=xxxxx&Action=Login"

  2. payload = {}
  3. headers = {
  4.   'User-Agent': 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.0 (KHTML, like Gecko)'
  5. }

  6. ctcResponse = requests.request("GET", url, headers=headers, data=payload)
  7. ctcResult = ctcResponse.text
  8. ctcmatch = re.findall("CTCGetAuthInfo\('(.*)'\)",ctcResult)
  9. ctc = ctcmatch[0]
复制代码
那么接下来就是加密生成Authenticator的值,机顶盒的password值获取方法和我之前的帖子江苏电信IPTV回看地址探究 (技术分析)中一样,这里不再赘述,但我推荐直接爆破。
Authenticator的生成,py代码如下
  1. key = "机顶盒的password值".encode("utf-8")
  2. text = "99999$"+ctc+"$iptv账号$机顶盒序列号$机顶盒ip地址$机顶盒MAC值$$CTC"
  3. crypter = DES.new(key, DES.MODE_ECB)
  4. Authenticator = crypter.encrypt(pkcs7_padding(text.encode("utf-8"))).hex().upper()
复制代码
Authenticator生成以后,还是/yniptv/register 但method变为post
  1. POST /yniptv/register HTTP/1.1
  2. Host: 112.115.0.132:11888
  3. Accept-Encoding: deflate, gzip
  4. Cookie: JSESSIONID=xxxx
  5. Connection: Keep-Alive
  6. Proxy-Connection: Keep-Alive
  7. Origin: http://112.115.0.132:11888
  8. Accept-Language: zh-CN,en-US;q=0.8
  9. User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.0 (KHTML, like Gecko)
  10. Content-Type: application/x-www-form-urlencoded
  11. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  12. Referer: http://112.115.0.132:11888/yniptv/register?UserID=xxxxx&Action=Login
  13. Content-Length: xxx

  14. UserID=xxxxxxxx&Authenticator=xxxxxxxxxxxxxxxxx
复制代码
py代码实现如下
  1. url = "http://112.115.0.132:11888/yniptv/register"

  2. payload = 'UserID=xxxx&Authenticator='+Authenticator
  3. headers = {
  4.   'Origin': 'http://112.115.0.132:11888',
  5.   'User-Agent': 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.0 (KHTML, like Gecko)',
  6.   'Content-Type': 'application/x-www-form-urlencoded',
  7.   'Referer': 'http://112.115.0.132:11888/yniptv/register?UserID=xxxxx&Action=Login'
  8. }

  9. registerResponse = requests.request("POST", url, headers=headers, data=payload)
  10. registerResult = registerResponse.text
  11. UserTokenMatch = re.findall("'UserToken','(\d*)'", registerResult)
  12. UserToken = UserTokenMatch[0]
  13. EncryptedUserTokenMatch = re.findall("'EncryptedUserToken','((\d|[A-Z])*)'", registerResult)
  14. EncryptedUserToken = EncryptedUserTokenMatch[0][0]
复制代码
这一步我们剥离两个数值UserToken 和EncryptedUserToken
接下来开始鉴权,包数据如下
  1. GET /EpgAuth?userToken=xxxx&stbNo=xxxx&userID=xxxxx&isNew=1&encryptedUserToken=xxxxx&areaNode=pe001&refreshTimeRandom=xxxxxxHTTP/1.1
  2. Host: 106.57.175.22:78
  3. Accept: */*
  4. Accept-Encoding: deflate, gzip
  5. Connection: Keep-Alive
  6. Proxy-Connection: Keep-Alive
  7. Accept-Language: zh-CN,en-US;q=0.8
  8. User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.0 (KHTML, like Gecko)
  9. Referer: http://106.57.175.22:78/iptv/ppthdplay/scrollcpapps/index/index.html

  10. HTTP/1.1 200 OK
  11. Date:
  12. Content-Type: text/plain;charset=UTF-8
  13. Content-Length: xxx
  14. Connection: keep-alive
  15. Expires:
  16. Cache-Control: no-cache
  17. X-XSS-Protection: 1; mode=block
  18. Pragma: no-cache
  19. X-Frame-Options: DENY
  20. X-Content-Type-Options: nosniff
  21. Cache-Control: no-cache
  22. Cache-Control: private

  23. {"description":"鉴权成功","epgGroupNMB":"xxxx","mac":"xxxxx","products":"xxxx","result":"0","stbID":"xxxx","tokenExpireTime":"","userGroupNMB":"xxx","userId":"xxx"}
复制代码
这一步中我们需要剥离products参数,py代码如下
  1. url = "http://106.57.175.22:78/EpgAuth?userToken="+UserToken+"&stbNo=xxxx&userID=xxxxx&isNew=1&encryptedUserToken="+EncryptedUserToken+"&areaNode=pe001&refreshTimeRandom=xxxx"

  2. payload = {}
  3. headers = {
  4.   'User-Agent': 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.0 (KHTML, like Gecko)',
  5.   'Referer': 'http://106.57.175.22:78/iptv/ppthdplay/scrollcpapps/index/index.html'
  6. }

  7. authResponse = requests.request("GET", url, headers=headers, data=payload)
  8. authResult = authResponse.text
  9. authJson = json.loads(authResult)
  10. products = authJson['products']
复制代码
下一步为获取频道信息,包如下
  1. POST /Channels HTTP/1.1
  2. Host: 106.57.175.22:78
  3. Accept-Encoding: deflate, gzip
  4. Cookie: dataCollectCache=%5B%5D; products=xxx
  5. Connection: Keep-Alive
  6. Proxy-Connection: Keep-Alive
  7. Origin: http://106.57.175.22:78
  8. Accept-Language: zh-CN,en-US;q=0.8
  9. X-Requested-With: XMLHttpRequest
  10. User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.0 (KHTML, like Gecko)
  11. Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  12. Accept: application/json, text/javascript, */*; q=0.01
  13. Referer: http://106.57.175.22:78/iptv/ppthdplay/scrollcpapps/index/specialSubject/PPT_BootAd/advertisePlay.html
  14. Content-Length: xxxx
  15. Expect: 100-continue

  16. channellistStr=xxxx
复制代码
py实现如下
  1. url = "http://106.57.175.22:78/Channels"

  2. payload = "channellistStr=xxx&userToken="+UserToken+"&userID=xxxx&isNew=1&isAntiTheftChain=false&encryptedUserToken="+EncryptedUserToken
  3. headers = {
  4.   'Cookie': 'dataCollectCache=[];products='+products,
  5.   'Origin': 'http://106.57.175.22:78',
  6.   'X-Requested-With': 'XMLHttpRequest',
  7.   'User-Agent': 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.0 (KHTML, like Gecko)',
  8.   'Referer': 'http://106.57.175.22:78/iptv/ppthdplay/scrollcpapps/index/specialSubject/PPT_BootAd/advertisePlay.html',
  9.   'Expect': '100-continue',
  10.   'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
  11. }

  12. channelsInfoResponse = requests.request("POST", url, headers=headers, data=payload)
  13. channelsInfoResult = channelsInfoResponse.text
  14. channelsInfoJson = json.loads(channelsInfoResult)
  15. channelGroups = channelsInfoJson['channelGroups']
  16. channelsInfo = []
  17. for group in channelGroups:
  18.       channels = group['channels']
  19.       for channel in channels:
  20.             channelTemp = {
  21.                   'channelCode': channel['channelCode'],
  22.                   'channelName': channel['channelName'],
  23.                   'groupName': channel['groupName']
  24.             }
  25.             channelsInfo.append(channelTemp)
复制代码
这一步剥离了频道code,频道名和分组
接下来是获取单播的url,包如下
  1. POST /EPG/jsp/getChannelPlayUrl?stbNo=xxxxx&userToken=xxxx&userID=xxxx&isNew=1&encryptedUserToken=xxxxx&refreshTimeRandom=xxxxx&areaNode=pe001 HTTP/1.1
  2. Host: 106.57.175.22:78
  3. Accept-Encoding: deflate, gzip
  4. Cookie: dataCollectCache=%5B%5D; products=xxxx
  5. Connection: Keep-Alive
  6. Proxy-Connection: Keep-Alive
  7. Origin: http://106.57.175.22:78
  8. Accept-Language: zh-CN,en-US;q=0.8
  9. X-Requested-With: XMLHttpRequest
  10. User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.0 (KHTML, like Gecko)
  11. Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  12. Accept: application/json, text/javascript, */*; q=0.01
  13. Referer: http://106.57.175.22:78/iptv/ppthdplay/scrollcpapps/index/specialSubject/PPT_BootAd/advertisePlay.html
  14. Content-Length: xxx
  15. Expect: 100-continue

  16. {"codes":
复制代码
py实现如下
  1. url = "http://106.57.175.22:78/EPG/jsp/getChannelPlayUrl?stbNo=xxxx&userToken="+UserToken+"&userID=xxx&isNew=1&encryptedUserToken="+EncryptedUserToken+"&
  2. refreshTimeRandom=xxx&areaNode=pe001"
  3. payload = "{"codes"xxxxxxx"<div>headers = {</div>  'Origin': 'http://106.57.175.22:78',
  4.   'Cookie': 'dataCollectCache=[];products='+products,
  5.   'X-Requested-With': 'XMLHttpRequest',
  6.   'User-Agent': 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.0 (KHTML, like Gecko)',
  7.   'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
  8.   'Referer': 'http://106.57.175.22:78/iptv/ppthdplay/scrollcpapps/index/specialSubject/PPT_BootAd/advertisePlay.html',
  9.   'Expect': '100-continue'
  10. }

  11. channelUrlResponse = requests.request("POST", url, headers=headers, data=payload)
  12. channelUrlResult = channelUrlResponse.text
  13. channelUrlJson = json.loads(channelUrlResult)
  14. channels = channelUrlJson['contentURL']
  15. m3uList = []
  16. for channel in channels:
  17.      channelCode = channel['code']
  18.      channelName = ''
  19.      channelGroup = ''
  20.      for ch in channelsInfo:
  21.            if ch['channelCode'] == channelCode:
  22.                  channelName =  ch['channelName']
  23.                  channelGroup = ch['groupName']
  24.      playUrl = channel['url']['playURL']
  25.      m3uList.append({
  26.            'channelName': channelName,
  27.            'playUrl' :playUrl,
  28.            'channelGroup': channelGroup
  29.      })
复制代码
在获取到播放url之后,和之前的channel基本信息组合,输出m3u数组对象
最后一步
输出m3u文件,也可按需输出txt等格式
  1. with open('./test.m3u', 'w', encoding="utf-8") as testm3u:
  2.       if len(m3uList) > 0:
  3.         testm3u.write("#EXTM3U\n")
  4.         for item in m3uList:
  5.                 if item['channelName'] != "":
  6.                   testm3u.write("#EXTINF:-1 group-title="+'"'+item['channelGroup']+'"'+","+item['channelName']+ "\n")
  7.                   testm3u.write(item['playUrl'] + "\n")
复制代码

2024.1.4 补充
在获取usertoken的同时需要获取JSESSIONID,代码如下
  1. JSESSIONID = registerResponse.cookies.get("JSESSIONID")
复制代码
上文中的106.57.175.22:78为动态值,估计是负载均衡导致每次的ip都不一样
更新方法如下
  1. url = "http://112.115.0.132:11888/yniptv/register?Action=getchannellist"

  2. payload = {}
  3. headers = {
  4.   'Cookie': 'JSESSIONID='+JSESSIONID+'; UserToken='+UserToken+';',
  5.   'User-Agent': 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.0 (KHTML, like Gecko)',
  6.   'Referer': 'http://112.115.0.132:11888/yniptv/register'
  7. }

  8. response = requests.request("GET", url, headers=headers, data=payload)
  9. slbipmatch = re.findall('document.location="http:\/\/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}).*', response.text)
  10. slbip = slbipmatch[0]
复制代码
所有106.57.175.22:78替换为剥离的slbip即可









只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
发表于 2024-1-3 19:29 来自手机 | 显示全部楼层
不错,牛人一个厉害
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

发表于 2024-1-3 19:30 来自手机 | 显示全部楼层
不错,牛人厉害
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

发表于 2024-1-3 22:45 来自手机 | 显示全部楼层
厉害厉害,够我捣腾好几天的。
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

发表于 2024-1-3 23:55 | 显示全部楼层
看不懂,有谁搞出来了发下成品
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

发表于 2024-1-18 08:52 | 显示全部楼层
怎么才能使用组播?
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 0 反对 1

使用道具 举报

头像被屏蔽
发表于 2024-1-31 18:41 | 显示全部楼层
提示: 该帖被管理员或版主屏蔽
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

发表于 2024-2-6 11:22 | 显示全部楼层
大神,我的抓出来的包在家里的网络内任何播放设备上都能正常使用,但只要出了家里的网络就用不了,这个是什么情况?
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

发表于 2024-2-8 10:00 | 显示全部楼层
wanhai1000 发表于 2024-2-6 11:22
大神,我的抓出来的包在家里的网络内任何播放设备上都能正常使用,但只要出了家里的网络就用不了,这个是什 ...

内网绑定宽带账户的…
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

发表于 2024-3-2 23:22 | 显示全部楼层
这个帖子要跟牢,原理知道没用,步骤知道也没用 ,不会编程啊,期待大佬出手搞定
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

发表于 2024-3-29 11:37 | 显示全部楼层
大神能做成本地运行文件吗?
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

发表于 2024-6-11 14:40 | 显示全部楼层
看着很厉害,可惜还是不太懂,自己抓包出来的地址,一个星期就失效。
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

发表于 2024-6-11 20:21 | 显示全部楼层
本地昆明,抓包出来的地址,全部一个都打不开,,,只能在机顶盒里正常打开看。。然后现在按照大佬的脚本,已经把机顶盒的8位密码破解出来了,后续的抽空了在慢慢接着搞了。
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

发表于 2024-6-15 03:09 | 显示全部楼层
整套流程走成功了,但现在只能看5秒左右,,就没有新的数据在缓冲了,切换到其他频道能看,但也是能看5秒,,估计是心跳包的问题?
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

发表于 2024-6-16 12:04 | 显示全部楼层
联系我,我是云南的我愿意付费,帮我解决一下
只谈技术、莫论政事!(点击见详情) | 恩山无线论坛欢迎您的来访,请互相尊重、友善交流,建议保持一颗平常心看待网友的评论,切勿过度反应。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

欢迎大家光临恩山无线论坛上一条 /1 下一条

有疑问请添加管理员QQ86788181|手机版|小黑屋|Archiver|恩山无线论坛(常州市恩山计算机开发有限公司版权所有) ( 苏ICP备05084872号 )

GMT+8, 2024-9-22 01:13

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

| 江苏省互联网有害信息举报中心 举报信箱:js12377 | @jischina.com.cn 举报电话:025-88802724 本站不良内容举报信箱:68610888@qq.com

快速回复 返回顶部 返回列表