今天来看一个swf格式的加密url逆向解析的例子:

简介

网页链接http://www.tvsky.tv/Industry/Show/278/33875/

通过浏览器加载进度条长度可以找到视频的地址:

视频详情:http://tvskysp.tvsky.tv:8082/hangyepindao/lvyou/16.flv
全局搜索视频详情中的部分关键元素也没有获得关键的信息:

鼠标指到视频上,在eletment页面找到加载的链接:

flvurl=lxxt4hGGB5e2T852Yfc5e2T88IFHl6b:b_3fOHU8s-qB2otjg3VfSc8-19K7_EhQ1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G29-Cl1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G296Cl1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G297Cl1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G298Cl1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G299Cl1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G29_Cl1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G2.Clr1a|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G2\Clr1a|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G2/Clr1a&isautoplay=1&adswf=

如果能把这一段解析出来,那么可能就是视频的真实播放url。

分析

那我们应该怎么做才能破解出这个URL呢?

首先,我们需要将这个页面上的Flash播放器给逆向一下,就像在爬HTML5视频网站碰到加密参数时逆向JavaScript一样。

但是Flash播放器是一个被编译后的.swf文件,我们并不能像JavaScript那样直接看到代码,需要先进行反编译。我们可以使用一款免费的flash反编译软件–JPEXS Free Flash Decompiler(FFDec),进行反编译。

github地址:https://github.com/jindrapetrik/jpexs-decompiler/releases
window版的下载地址:
https://github.com/jindrapetrik/jpexs-decompiler/releases/download/nightly1712/ffdec_11.2.0_nightly1712_setup.exe
安装的时候选择中文,直接下一步,中间要装一个java 1.8版本的jdk,选择默认安装即可。装好后如下:

安装好后,将element页的swf文件给下载下来:http://www.tvsky.tv/FlvPlay/Playerx.swf,它就是逆向对象。

用软件打开下载下来的swf文件,如下:

查看frame1 下面的DoAction脚本,大致浏览,脚本一共496行,很短,可以看到一些方法,如init(),可以可看到“正在加载Flv文件”,“正在缓冲”等操作视频的中文,可按ctrl+F进行搜索到,也可以搜索“flvurl”看一看在哪些地方出现(搜索flvurl是由于我们要解密的对象就是这种样式flvurl=lxxt4hGGB5e2T852Yfc5e2T88IFHl6b:b_3fOHU8s-qB2otjg3VfSc8-19K7_EhQ1Qa…),发现只有第35行出现过:

敏感的发现这个init就是我们需要的相关代码。

function init()
{_isautoplay = isautoplay;_title = titlecon;_ggswf = adswf;var _loc2_ = flvurl;if(_loc2_ == undefined || _loc2_ == null){_loc2_ = "";}else{_flvurl = _loc2_.split("|");var _loc1_ = 0;while(_loc1_ < _flvurl.length){_flvurl[_loc1_] = Pass2Str(_flvurl[_loc1_]);_loc1_ = _loc1_ + 1;}}if(_ggswf == undefined || _ggswf == null){_ggswf = "";}if(_ggswf.length == 0){b_load._visible = true;b_load.gotoAndStop(1);yqbutton.loadflv._visible = true;yqbutton.loadflv.loadflv.text = "正在加载Flv文件";flvpp = setTimeout(FlvPlay,2000);}
}

代码当中的Pass2Str()与它当中的NumS()方法都定位到:

function SNum(s, _PwdAddLen1)
{var _loc1_ = PwdStr.indexOf(s);_loc1_ = _loc1_ + (_PwdAddLen + _PwdAddLen1 + 1);if(_loc1_ > PwdStr.length){return PwdStr.substr(_loc1_ - PwdStr.length,1);}return PwdStr.substr(_loc1_,1);
}
function NumS(s, _PwdAddLen1)
{var _loc1_ = PwdStr.indexOf(s);_loc1_ = _loc1_ - (_PwdAddLen + _PwdAddLen1 - 1);if(_loc1_ <= 0){return PwdStr.substr(_loc1_ + PwdStr.length,1);}return PwdStr.substr(_loc1_,1);
}
function Pass2Str(Str)
{var _loc2_ = "";var _loc3_ = "";var _loc4_ = 0;var _loc1_ = 1;while(_loc1_ <= Str.length){_loc2_ = Str.substr(_loc1_,1);if(_loc1_ % (_PwdLen + 1) != 0){_loc3_ = _loc3_ + NumS(_loc2_,_loc4_);}else{_loc4_ = parseInt(_loc2_);}_loc1_ = _loc1_ + 1;}return _loc3_;
}
stop();
Stage.align = "TL";
Stage.scaleMode = "noScale";
myMenu = new ContextMenu();
myMenu.hideBuiltInItems();
_root.menu = myMenu;
var PwdStr = "AbCdEfGhIjKlMnOpQrStUvWxYzaBcDeFgHiJkLmNoPqRsTuVwXyZ1234509876-_.\\/:";
var PwdStrRan = "12345678987654321";
var _PwdLen = 4;
var adTimeId = "";
var adTimeIdtime = 0;
var _PwdAddLen = 4;

代码

将上面的代码翻译成python语言,如下:
注意需要将要解析的字符串进行处理,每一个“|”是一条url(通过测试发现):

flvurl=lxxt4hGGB5e2T852Yfc5e2T88IFHl6b:b_3fOHU8s-qB2otjg3VfSc8-19K7_EhQ1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G29-Cl1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G296Cl1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G297Cl1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G298Cl1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G299Cl1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G29_Cl1Qa|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G2.Clr1a|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G2\Clr1a|lxxt3Gffa8H5w-85BIF3cZR06GDFj6b:b_6Irkx9T_Rc2otjg1TdQa49w3G2/Clr1a&isautoplay=1&adswf=
_pwd_len = 4
_pwd_add_len = 4
pwd_str = "AbCdEfGhIjKlMnOpQrStUvWxYzaBcDeFgHiJkLmNoPqRsTuVwXyZ1234509876-_.\\/:"def decode(flv_url: str):"""function init(){......var _loc2_ = flvurl;......_flvurl = _loc2_.split("|");var _loc1_ = 0;while(_loc1_ < _flvurl.length){_flvurl[_loc1_] = Pass2Str(_flvurl[_loc1_]);_loc1_ = _loc1_ + 1;}......}:param flv_url: flash参数里的flvurl部分的value:return: 解密后视频url列表"""new_flv_url = flv_url.split("|")_loc1_ = 0while _loc1_ < len(new_flv_url):new_flv_url[_loc1_] = pass2str(new_flv_url[_loc1_])_loc1_ += 1return new_flv_urldef pass2str(str_: str):"""function Pass2Str(Str){var _loc2_ = "";var _loc3_ = "";var _loc4_ = 0;var _loc1_ = 1;while(_loc1_ <= Str.length){_loc2_ = Str.substr(_loc1_,1);if(_loc1_ % (_PwdLen + 1) != 0){_loc3_ = _loc3_ + NumS(_loc2_,_loc4_);}else{_loc4_ = parseInt(_loc2_);}_loc1_ = _loc1_ + 1;}return _loc3_;}:param str_: 加密的url字符串:return: 解密后的url字符串"""_loc1_ = 1_loc3_ = ""_loc4_ = 0while _loc1_ <= len(str_):_loc2_ = str_[_loc1_ - 1]if _loc1_ % (_pwd_len + 1) != 0:_loc3_ = _loc3_ + num_s(_loc2_, _loc4_)else:_loc4_ = int(_loc2_) if _loc2_.isdigit() else 0_loc1_ = _loc1_ + 1return _loc3_def num_s(s, _pwd_add_len1):"""function NumS(s, _PwdAddLen1){var _loc1_ = PwdStr.indexOf(s);_loc1_ = _loc1_ - (_PwdAddLen + _PwdAddLen1 - 1);if(_loc1_ <= 0){return PwdStr.substr(_loc1_ + PwdStr.length,1);}return PwdStr.substr(_loc1_,1);}"""_loc1_ = pwd_str.index(s)_loc1_ = _loc1_ - (_pwd_add_len + _pwd_add_len1 - 1)if _loc1_ <= 0:return pwd_str[_loc1_ + len(pwd_str) - 1]return pwd_str[_loc1_ - 1]if __name__ == '__main__':str_url = "lxxt4hGGB5e2T852Yfc5e2T88IFHl6b:b_3fOHU8s-qB2otjg3VfSc8-19K7_EhQ1Qa"   # 解析当前播放的视频url_list = decode(str_url)print(url_list)    # 输出:http://tvskysp.tvsky.tv:8082/hangyepindao/lvyou/16.flv

总结

1.要仔细观察加密对象,尝试不同的办法解码,比如美拍的后半段是base64加密后得到的。
2.本例中的字符串对象,是多个url加密后的地址,中间通过“|”组合在一块的,但是每一条都很相似,判断它们是同一个东西。

如果你有空,可以想一想为什么使用js不能得到正确的结果,这有助于你理解python调用js:

js_content = """
function NumS(s, _PwdAddLen1)
{var _loc1_ = PwdStr.indexOf(s);_loc1_ = _loc1_ - (_PwdAddLen + _PwdAddLen1 - 1);if(_loc1_ <= 0){return PwdStr.substr(_loc1_ + PwdStr.length,1);}return PwdStr.substr(_loc1_,1);
}
function Pass2Str(Str)
{var _loc2_ = "";var _loc3_ = "";var _loc4_ = 0;var _loc1_ = 1;while(_loc1_ <= Str.length){_loc2_ = Str.substr(_loc1_,1);if(_loc1_ % (_PwdLen + 1) != 0){_loc3_ = _loc3_ + NumS(_loc2_,_loc4_);}else{_loc4_ = parseInt(_loc2_);}_loc1_ = _loc1_ + 1;}return _loc3_;}
var PwdStr = "AbCdEfGhIjKlMnOpQrStUvWxYzaBcDeFgHiJkLmNoPqRsTuVwXyZ1234509876-_.\\/:";
var PwdStrRan = "12345678987654321";
var _PwdLen = 4;
var adTimeId = "";
var adTimeIdtime = 0;
var _PwdAddLen = 4;
"""url_str = "lxxt5Ihhc3cZR01XUbY2Byq57hegK3/./77jSLY1L4JU4qvli2uErB30V2f8.fIr4tD"
import execjs
jsContent = execjs.compile(js_content)
print(jsContent.call("Pass2Str",url_str))
# 输出:UUQ2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsyC5AAAAAA
# 答案在文章中就有,你发现了吗?

参考知乎文章:https://zhuanlan.zhihu.com/p/45508079

逆向破解flash视频url相关推荐

  1. js逆向破解 —— 懂车帝视频链接

    背景 话说下午有一朋友发我一链接懂车帝某视频,让我帮忙看一下这个网页中视频链接是怎么获取的.我断断续续地花了两三个小时,最后终于把它给拿下了.在整个分析的过程中,我觉得还算是有点意思,所以写下这便博客 ...

  2. 技术分享:逆向破解华为路由器第三部分

    技术分享:逆向破解华为路由器第三部分 引文 在前面两个部分(1,2)已经介绍了UART,BusyBox等部分的逆向调试,而这篇将会开始在流量分析方面下手,来逆向出更多的信息. 正文 请看下图,数据存储 ...

  3. 【CrackMe 实战】逆向破解实战之 001 Acid burn.exe

    CrackMe:是一些公开给别人尝试破解的小程序,制作 crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 cracker,想挑战一下其它 cracker 的破解实力,也可能 ...

  4. html怎么导入flash视频,DW如何在网页中插入Flash视频?

    在 Dreamweaver 的"文档"窗口中打开 index.html 页面,插入一个三列的表格,在由三列组成的表格的中间一列中放置的图形之上单击一次. 选择"插入&qu ...

  5. html添加flash视频,添加视频模块和Flash模块

    1. 添加视频模块: 建站系统可以通过两种方方式去添加视频. 1) 视频URL添加法.这种添加法允许添加的是其它站点的视频URL 第一步:在视频源网站找到该视频的URL链接地址,该链接地址必须以.mp ...

  6. dw8 html视频教程,DW8在网页中轻松插入Flash视频

    在 Dreamweaver 的"文档"窗口中打开 index.html 页面,插入一个三列的表格,在由三列组成的表格的中间一列中放置的图形之上单击一次. 选择"插入&qu ...

  7. dw8制作html手机兼容视频,Dreamweaver8在网页中插入Flash视频

    在 Dreamweaver 的"文档"窗口中打开 index.html 页面,插入一个三列的表格,在由三列组成的表格的中间一列中放置的图形之上单击一次. 选择"插入&qu ...

  8. 技术分享:逆向破解华为路由器第二部分

    技术分享:逆向破解华为路由器第二部分 引文 在第一部分,我通过UART进行了调试,并在最后利用命令行页面利用shell 命令就可以获取root权限了.也就是在这一点上,我已经可以访问路由器了,之后就可 ...

  9. 2019年末逆向复习系列之百度指数Data加密逆向破解

    郑重声明:本项目的所有代码和相关文章, 仅用于经验技术交流分享,禁止将相关技术应用到不正当途径,因为滥用技术产生的风险与本人无关. 这篇文章是公众号<云爬虫技术研究笔记>的<2019 ...

  10. GJM:移动App入侵与逆向破解技术-iOS篇 【转载】

    GJM:移动App入侵与逆向破解技术-iOS篇 [转载] 转载: URL http://dev.qq.com/topic/577e0acc896e9ebb6865f321 如果您有耐心看完这篇文章,您 ...

最新文章

  1. Sublime Text 3 及Package Control 安装(附上一个3103可用的Key)
  2. 初创互联网公司简明创业指南 - YC新掌门Sam Altman
  3. 使用观察者模式在 Silverlight 中切换用户控件
  4. 算法设计与分析——算法思想总结
  5. 十四、Canny边缘提取
  6. 【转】Dynamics 365Online 如何启用手机端APP的离线功能
  7. Neural Style Transfer 神经风格迁移详解
  8. 如果创业遍地,你觉得会是怎么样的景象
  9. 历年计算机二级考试Java真题 JAVA笔试试题及答案(部分套题)
  10. ORACLE数据库字段类型说明
  11. aardio部署_aardio写网站部署到服务器步骤
  12. 【情人节表白神器:送她一个HTML动态表白网站 带源码】
  13. Cdboot:couldn‘t find bootmgr
  14. 用python模拟登录12306
  15. 工业物联网有什么特征
  16. JS身份证号码校验,JS根据身份证号码获取出生年月日,JS根据出生年月日获取年龄,JS根据身份证号码获取性别
  17. Intel有那些45纳米的CPU
  18. android更新软件,Android软件的自动更新
  19. 实体类字段定义错误:java.sql.SQLSyntaxErrorException: Column ‘xxx‘ specified twice
  20. 关于麦克风的参数介绍 - 驻极体麦克风(ECM)和硅麦(MEMS)

热门文章

  1. 基于MATLAB的有源三相滤波器的设计,基于MATLAB的有源滤波器的设计与仿真
  2. 高通平台开发系列讲解(外设篇)BMI160基本配置
  3. mysql 多重循环_SQL循环语句 详解
  4. IPv4地址中的保留和特殊用途地址
  5. win10解压文件时,出错:不能创建符号链接 你可能需要以管理员权限运行Winrar 客户端没有所需的特权
  6. 校招行测笔试-图形推理
  7. Flink窗口-时间窗口
  8. 华硕aura完全卸载_AURA神光同步是什么意思?AURA SYNC神光同步教程
  9. 蓝牙安全与攻击案例分析
  10. 《ANSYS Workbench有限元分析实例详解(静力学)》——第1章 CAE分析步骤1.1 模型简化...