易企秀H5 json配置文件解密分析
最近需要参考下易企秀H5的json配置文件,发现已经做了加密,其实前端的加密分析起来只是麻烦点。
抓包分析
先看一个H5: https://h5.eqxiu.com/s/XvEn30op
F12可以看到,配置json地址是:https://s1-cdn.eqxiu.com/eqs/page/142626394?code=XvEn30op&time=1542972816000
对应的json:
{"success":true,"code":200,"msg":"操作成功","obj":"加密后的字符串"}
obj对应的是正式的配置信息
解码分析
需要对加密信息进行解密,首先可以定位到解密代码
function _0x230bc7(_0x2fb175) {
return _0x3c31('0xee') == typeof _0x2fb175[_0x3c31('0x25')] && _0x2fb175['\x6f\x62\x6a'][_0x3c31('0xe')] > 0x64 ? _0x54c90c[_0x3c31('0x31f')]()['\x74\x68\x65\x6e'](function() {
_0x249a60();
var _0x5ab652 = null
, _0x2cf0a4 = null
, _0x4d1175 = null;
try {
var _0x3dbfaa = _0x2fb175[_0x3c31('0x25')]['\x73\x75\x62\x73\x74\x72\x69\x6e\x67'](0x0, 0x13)
, _0x360e25 = _0x2fb175[_0x3c31('0x25')][_0x3c31('0xeb')](0x13 + 0x10);
_0x2cf0a4 = _0x2fb175[_0x3c31('0x25')][_0x3c31('0xeb')](0x13, 0x13 + 0x10),
_0x4d1175 = _0x2cf0a4,
_0x5ab652 = _0x3dbfaa + _0x360e25,
_0x2cf0a4 = CryptoJS['\x65\x6e\x63'][_0x3c31('0x320')][_0x3c31('0x6b')](_0x2cf0a4),
_0x4d1175 = CryptoJS[_0x3c31('0x321')][_0x3c31('0x320')]['\x70\x61\x72\x73\x65'](_0x4d1175);
var _0x57e61a = CryptoJS[_0x3c31('0x322')][_0x3c31('0x323')](_0x5ab652, _0x2cf0a4, {
'\x69\x76': _0x4d1175,
'\x6d\x6f\x64\x65': CryptoJS[_0x3c31('0x324')][_0x3c31('0x325')],
'\x70\x61\x64\x64\x69\x6e\x67': CryptoJS[_0x3c31('0x326')][_0x3c31('0x327')]
});
return _0x2fb175[_0x3c31('0x36')] = JSON[_0x3c31('0x6b')](CryptoJS[_0x3c31('0x321')][_0x3c31('0x320')][_0x3c31('0x267')](_0x57e61a)),
_0x2fb175;
} catch (_0x36fffe) {
_0x5ab652 = _0x2fb175[_0x3c31('0x25')]['\x73\x75\x62\x73\x74\x72\x69\x6e\x67'](0x0, _0x2fb175[_0x3c31('0x25')][_0x3c31('0xe')] - 0x10),
_0x2cf0a4 = _0x2fb175[_0x3c31('0x25')][_0x3c31('0xeb')](_0x2fb175[_0x3c31('0x25')][_0x3c31('0xe')] - 0x10),
_0x4d1175 = _0x2cf0a4,
_0x2cf0a4 = CryptoJS[_0x3c31('0x321')][_0x3c31('0x320')][_0x3c31('0x6b')](_0x2cf0a4),
_0x4d1175 = CryptoJS[_0x3c31('0x321')][_0x3c31('0x320')][_0x3c31('0x6b')](_0x4d1175);
var _0x4ff7de = CryptoJS[_0x3c31('0x322')][_0x3c31('0x323')](_0x5ab652, _0x2cf0a4, {
'\x69\x76': _0x4d1175,
'\x6d\x6f\x64\x65': CryptoJS['\x6d\x6f\x64\x65'][_0x3c31('0x325')],
'\x70\x61\x64\x64\x69\x6e\x67': CryptoJS[_0x3c31('0x326')][_0x3c31('0x327')]
});
return _0x2fb175[_0x3c31('0x36')] = JSON[_0x3c31('0x6b')](CryptoJS[_0x3c31('0x321')]['\x55\x74\x66\x38'][_0x3c31('0x267')](_0x4ff7de)),
_0x2fb175;
}
}) : Promise[_0x3c31('0x1e')](_0x2fb175);
这个代码基本不可读,简单分析下可以发现,_0x3c31('0x321')对应一个字符串,'\x6f\x62\x6a'等也可以转义:
先转义:
function decode(xData) {
return xData.replace(/\\x(\w{2})/g, function (_, $1) { return String.fromCharCode(parseInt($1, 16)) });
}
然后替换下:
Function.prototype.getMultiLine = function () {
var lines = new String(this);
lines = lines.substring(lines.indexOf("/*") + 3, lines.lastIndexOf("*/"));
return lines;
}
function decode(xData) {
return xData.replace(/\\x(\w{2})/g, function (_, $1) { return String.fromCharCode(parseInt($1, 16)) });
}
var str1 = function () {
/*
var _0x5ab652 = _0x50019d(_0x3c31('0x30c'))
, _0x2cf0a4 = _0x50019d('\x63\x6f\x6d\x70\x4b\x65\x79')
, _0x5cba8a = {
'\x74\x79\x70\x65': _0x3c31('0x16c'),
'\x75\x72\x6c': _0x8aa6f1()
}
, _0xfca4af = {
'\x74\x79\x70\x65': _0x3c31('0x16c'),
'\x75\x72\x6c': _0xefaeb()
};
_0x31f1b8 && (_0x5cba8a[_0x3c31('0x2cb')] = {
'\x70\x61\x73\x73\x77\x6f\x72\x64': _0x31f1b8
});
var _0x11871b = null
, _0x170c7e = Promise[_0x3c31('0x1e')](null);
var _0x256cd0 = _0x2cf0a4(0x16)
, _0x36150e = _0x2cf0a4(0x15)
, _0x42a8d9 = _0x36150e['\x61\x6a\x61\x78']
, _0xdc46dc = _0x36150e[_0x3c31('0x1ef')]
, _0xcca797 = _0x2cf0a4(0x18)
, _0x50019d = _0xcca797[_0x3c31('0x5f')]
, _0x5c77e3 = _0xcca797['\x70\x61\x72\x73\x65\x55\x72\x6c']
, _0x36d54a = _0x2cf0a4(0x3a)['\x70\x65\x72\x66\x65\x63\x74\x4d\x65\x74\x61']
, _0x4c6a9e = _0x2cf0a4(0x2c)[_0x3c31('0x328')]
, _0x296a9b = _0x2cf0a4(0x2c)[_0x3c31('0x329')]
, _0x54c90c = _0x2cf0a4(0x17)
, _0x50f238 = _0x2cf0a4(0x3d)[_0x3c31('0x32a')]
, 0x13 = 0x13
, 0x0 = 0x0
, 0x10 = 0x10
, CryptoJS = null;
function _0x230bc7(_0x2fb175) {
return _0x3c31('0xee') == typeof _0x2fb175[_0x3c31('0x25')] && _0x2fb175['\x6f\x62\x6a'][_0x3c31('0xe')] > 0x64 ? _0x54c90c[_0x3c31('0x31f')]()['\x74\x68\x65\x6e'](function() {
_0x249a60();
var _0x5ab652 = null
, _0x2cf0a4 = null
, _0x4d1175 = null;
try {
var _0x3dbfaa = _0x2fb175[_0x3c31('0x25')]['\x73\x75\x62\x73\x74\x72\x69\x6e\x67'](0x0, 0x13)
, _0x360e25 = _0x2fb175[_0x3c31('0x25')][_0x3c31('0xeb')](0x13 + 0x10);
_0x2cf0a4 = _0x2fb175[_0x3c31('0x25')][_0x3c31('0xeb')](0x13, 0x13 + 0x10),
_0x4d1175 = _0x2cf0a4,
_0x5ab652 = _0x3dbfaa + _0x360e25,
_0x2cf0a4 = CryptoJS['\x65\x6e\x63'][_0x3c31('0x320')][_0x3c31('0x6b')](_0x2cf0a4),
_0x4d1175 = CryptoJS[_0x3c31('0x321')][_0x3c31('0x320')]['\x70\x61\x72\x73\x65'](_0x4d1175);
var _0x57e61a = CryptoJS[_0x3c31('0x322')][_0x3c31('0x323')](_0x5ab652, _0x2cf0a4, {
'\x69\x76': _0x4d1175,
'\x6d\x6f\x64\x65': CryptoJS[_0x3c31('0x324')][_0x3c31('0x325')],
'\x70\x61\x64\x64\x69\x6e\x67': CryptoJS[_0x3c31('0x326')][_0x3c31('0x327')]
});
return _0x2fb175[_0x3c31('0x36')] = JSON[_0x3c31('0x6b')](CryptoJS[_0x3c31('0x321')][_0x3c31('0x320')][_0x3c31('0x267')](_0x57e61a)),
_0x2fb175;
} catch (_0x36fffe) {
_0x5ab652 = _0x2fb175[_0x3c31('0x25')]['\x73\x75\x62\x73\x74\x72\x69\x6e\x67'](0x0, _0x2fb175[_0x3c31('0x25')][_0x3c31('0xe')] - 0x10),
_0x2cf0a4 = _0x2fb175[_0x3c31('0x25')][_0x3c31('0xeb')](_0x2fb175[_0x3c31('0x25')][_0x3c31('0xe')] - 0x10),
_0x4d1175 = _0x2cf0a4,
_0x2cf0a4 = CryptoJS[_0x3c31('0x321')][_0x3c31('0x320')][_0x3c31('0x6b')](_0x2cf0a4),
_0x4d1175 = CryptoJS[_0x3c31('0x321')][_0x3c31('0x320')][_0x3c31('0x6b')](_0x4d1175);
var _0x4ff7de = CryptoJS[_0x3c31('0x322')][_0x3c31('0x323')](_0x5ab652, _0x2cf0a4, {
'\x69\x76': _0x4d1175,
'\x6d\x6f\x64\x65': CryptoJS['\x6d\x6f\x64\x65'][_0x3c31('0x325')],
'\x70\x61\x64\x64\x69\x6e\x67': CryptoJS[_0x3c31('0x326')][_0x3c31('0x327')]
});
return _0x2fb175[_0x3c31('0x36')] = JSON[_0x3c31('0x6b')](CryptoJS[_0x3c31('0x321')]['\x55\x74\x66\x38'][_0x3c31('0x267')](_0x4ff7de)),
_0x2fb175;
}
}) : Promise[_0x3c31('0x1e')](_0x2fb175);
}"
*/
}
var js1 = decode(str1.getMultiLine());
js1 = js1.replace(/_0x3c31\('([^\']+)'\)/g, function ($v, $g) { return _0x3c31($g); })
得到
var _0x5ab652 = _0x50019d(userKey)
, _0x2cf0a4 = _0x50019d('compKey')
, _0x5cba8a = {
'type': GET,
'url': _0x8aa6f1()
}
, _0xfca4af = {
'type': GET,
'url': _0xefaeb()
};
_0x31f1b8 && (_0x5cba8a[data] = {
'password': _0x31f1b8
});
var _0x11871b = null
, _0x170c7e = Promise[resolve](null);
var _0x256cd0 = _0x2cf0a4(0x16)
, _0x36150e = _0x2cf0a4(0x15)
, _0x42a8d9 = _0x36150e['ajax']
, _0xdc46dc = _0x36150e[$ajax]
, _0xcca797 = _0x2cf0a4(0x18)
, _0x50019d = _0xcca797[getUrlParam]
, _0x5c77e3 = _0xcca797['parseUrl']
, _0x36d54a = _0x2cf0a4(0x3a)['perfectMeta']
, _0x4c6a9e = _0x2cf0a4(0x2c)[isVipScene]
, _0x296a9b = _0x2cf0a4(0x2c)[isTgScene]
, _0x54c90c = _0x2cf0a4(0x17)
, _0x50f238 = _0x2cf0a4(0x3d)[setJsCrypto]
, 0x13 = 0x13
, 0x0 = 0x0
, 0x10 = 0x10
, CryptoJS = null;
function _0x230bc7(_0x2fb175) {
return string == typeof _0x2fb175[obj] && _0x2fb175['obj'][length] > 0x64 ? _0x54c90c[$loadCryptoJS]()['then'](function() {
_0x249a60();
var _0x5ab652 = null
, _0x2cf0a4 = null
, _0x4d1175 = null;
try {
var _0x3dbfaa = _0x2fb175[obj]['substring'](0x0, 0x13)
, _0x360e25 = _0x2fb175[obj][substring](0x13 + 0x10);
_0x2cf0a4 = _0x2fb175[obj][substring](0x13, 0x13 + 0x10),
_0x4d1175 = _0x2cf0a4,
_0x5ab652 = _0x3dbfaa + _0x360e25,
_0x2cf0a4 = CryptoJS['enc'][Utf8][parse](_0x2cf0a4),
_0x4d1175 = CryptoJS[enc][Utf8]['parse'](_0x4d1175);
var _0x57e61a = CryptoJS[AES][decrypt](_0x5ab652, _0x2cf0a4, {
'iv': _0x4d1175,
'mode': CryptoJS[mode][CFB],
'padding': CryptoJS[pad][NoPadding]
});
return _0x2fb175[list] = JSON[parse](CryptoJS[enc][Utf8][stringify](_0x57e61a)),
_0x2fb175;
} catch (_0x36fffe) {
_0x5ab652 = _0x2fb175[obj]['substring'](0x0, _0x2fb175[obj][length] - 0x10),
_0x2cf0a4 = _0x2fb175[obj][substring](_0x2fb175[obj][length] - 0x10),
_0x4d1175 = _0x2cf0a4,
_0x2cf0a4 = CryptoJS[enc][Utf8][parse](_0x2cf0a4),
_0x4d1175 = CryptoJS[enc][Utf8][parse](_0x4d1175);
var _0x4ff7de = CryptoJS[AES][decrypt](_0x5ab652, _0x2cf0a4, {
'iv': _0x4d1175,
'mode': CryptoJS['mode'][CFB],
'padding': CryptoJS[pad][NoPadding]
});
return _0x2fb175[list] = JSON[parse](CryptoJS[enc]['Utf8'][stringify](_0x4ff7de)),
_0x2fb175;
}
}) : Promise[resolve](_0x2fb175);
}"
基板上可以读了,使用CryptoJS做的前端解密,然后直接给最后的代码:
// 依赖: https://lib.eqh5.com/CryptoJS/1.0.1/cryptoJs.js
function decrypt(result) {
var ciphertext = null
, key = null
, iv = null;
try {
var part0 = result.obj.substring(0x0, 0x13)
, part1 = result.obj.substring(0x13 + 0x10);
key = result.obj.substring(0x13, 0x13 + 0x10),
iv = key,
ciphertext = part0 + part1,
key = CryptoJS.enc.Utf8.parse(key),
iv = CryptoJS.enc.Utf8.parse(iv);
var decryptData = CryptoJS.AES.decrypt(ciphertext, key, {
'iv': iv,
'mode': CryptoJS.mode.CFB,
'padding': CryptoJS.pad.NoPadding
});
return CryptoJS.enc.Utf8.stringify(decryptData);
} catch (_0x36fffe) {
ciphertext = result[obj]['substring'](0x0, result.obj.length - 0x10),
key = result[obj][substring](result.obj.length - 0x10),
iv = key,
key = CryptoJS.enc.Utf8.parse(key),
iv = CryptoJS.enc.Utf8.parse(iv);
var decryptData = CryptoJS.AES.decrypt(ciphertext, key, {
'iv': iv,
'mode': CryptoJS.mode.CFB,
'padding': CryptoJS.pad.NoPadding
});
return CryptoJS.enc.Utf8.stringify(decryptData)
}
}
易企秀H5 json配置文件解密分析的更多相关文章
- 如何搭建易企秀H5平台?
导读 易企秀如何开启伪静态支持? 一秀如何开启伪静态? 下载易企秀源码 oschina: http://git.oschina.net/jsper/html5Editor Windows下搭建环境 安 ...
- H5类似易企秀/编辑器/页面制作/开发/生成工具/软件/源码/授权
代码地址如下:http://www.demodashi.com/demo/14960.html 项目简介 H5DS (HTML5 Design software) 这是一款基于WEB的 H5制作工具. ...
- 易企秀 we+ Maka 兔展 四大H5页面制作工具
H5这个由HTML5简化而来的词汇,正通过微信广泛传播.H5是集文字.图片.音乐.视频.链接等多种形式的展示页面,丰富的控件.灵活的动画特效.强大的交互应用和数据分析,高速低价的实现信息传播,非常适合 ...
- H5易企秀
周末被领导叫回来加班,说要做一个易企秀一样的页面,然后就有这篇笔记 原计划用几百个计时器去执行,后面放弃了,太难改了,还是选择了animate.css插件,这是一个纯css的插件,只需要引入css就行 ...
- 易企秀微场景2016最新完整版V10.5,小编亲测修复众多错误
易企秀V10.5更新说明1.修复拨号英文错误2.修复转送场景问题3.修复设置场景密码乱码问题4.修复前台批量删除客户图片5.修复数据收集分页问题6.修复图片分类错乱问题7.修复音乐和特效冲突问题8.修 ...
- 【krpano】加密XML手动解密分析
krpano允许对XML文件进行加密,对XML进行相应的保护.加密分为两种,第一种为公共加密,即允许其他krpano全景读取该XML,而另一种为私有加密,仅允许加密的用户读取XML.两种加密方式的算法 ...
- .Net Core Linux centos7行—.net core json 配置文件
.net core 对配置系统做出了大幅度更新,不在局限于之前的*.xml配置方式.现在支持json,xml,ini,in memory,环境变量等等.毫无疑问的是,现在的json配置文件是.net ...
- [.NET Core] 简单读取 json 配置文件
简单读取 json 配置文件 背景 目前发现网上的 .NET Core 读取配置文件有点麻烦,自己想搞个简单点的. .NET Core 已经不使用之前的诸如 app.config 和 web.conf ...
- Asp .Net Core 读取appsettings.json配置文件
Asp .Net Core 如何读取appsettings.json配置文件?最近也有学习到如何读取配置文件的,主要是通过 IConfiguration,以及在Program中初始化完成的. ...
随机推荐
- 2.4G和5G的Wi-Fi各自优缺点对比
原文地址:http://service.tp-link.com.cn/detail_article_3366.html 1.为什么5G信号的穿墙效果比2.4G信号差? 与路由器的距离相同时,5G信号相 ...
- NOI2019 SX 模拟赛 no.5
Mas 的童年 题目描述:不知道传送门有没有用? 反正就是对于每个前缀序列求一个断点,使得断点左右两个区间的 分别的异或和 的和最大 分析 jzoj 原题? 但是我 TM 代码没存账号也过期了啊! 然 ...
- ansible笔记(7):常用模块之系统类模块
ansible笔记():常用模块之系统类模块 cron模块 cron模块可以帮助我们管理远程主机中的计划任务,功能相当于crontab命令. 在了解cron模块的参数之前,先写出一些计划任务的示例,示 ...
- centos系统初始化配置
.改主机名: sed -i 's#HOSTNAME=.*#HOSTNAME=u05mix06.yaya.corp#g' /etc/sysconfig/network && hostna ...
- matlab求导数
clc; %清屏 clear; %清除变量 close all; %关闭 syms x; %定义变量,多个变量间用空格分离 f(x) = x^3; %原函数 res = diff(f(x),x,1); ...
- python第13天
装饰器 装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何改动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象. 装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等 ...
- zxing源码编译与运行
编译的jar文件下载地址:http://files.cnblogs.com/rainboy2010/zxing.zip zxing是一个开源的解析条形码/二维码的类库,广泛应用于Android 各大A ...
- html5中如何去掉input type date默认
html5中如何去掉input type date默认样式 2.对日期时间控件的样式进行修改目前WebKit下有如下9个伪元素可以改变日期控件的UI:::-webkit-datetime-edit – ...
- Linux文件系统深度讨论【转】
本文旨在对Linux文件系统概念高级工作方式进行的讨论,不是对特定文件系统类型(如EXT4)如何工作的低级描述,也不是对文件系统命令的教程. 每台通用计算机都需要将各种类型的数据存储在硬盘驱动器( ...
- Swift 学习- 02 -- 基础部分2
class NamedShape{ var numberOfSides: Int = 0 var name: String init(name: String) { self.name = name ...