最近需要参考下易企秀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配置文件解密分析的更多相关文章

  1. 如何搭建易企秀H5平台?

    导读 易企秀如何开启伪静态支持? 一秀如何开启伪静态? 下载易企秀源码 oschina: http://git.oschina.net/jsper/html5Editor Windows下搭建环境 安 ...

  2. H5类似易企秀/编辑器/页面制作/开发/生成工具/软件/源码/授权

    代码地址如下:http://www.demodashi.com/demo/14960.html 项目简介 H5DS (HTML5 Design software) 这是一款基于WEB的 H5制作工具. ...

  3. 易企秀 we+ Maka 兔展 四大H5页面制作工具

    H5这个由HTML5简化而来的词汇,正通过微信广泛传播.H5是集文字.图片.音乐.视频.链接等多种形式的展示页面,丰富的控件.灵活的动画特效.强大的交互应用和数据分析,高速低价的实现信息传播,非常适合 ...

  4. H5易企秀

    周末被领导叫回来加班,说要做一个易企秀一样的页面,然后就有这篇笔记 原计划用几百个计时器去执行,后面放弃了,太难改了,还是选择了animate.css插件,这是一个纯css的插件,只需要引入css就行 ...

  5. 易企秀微场景2016最新完整版V10.5,小编亲测修复众多错误

    易企秀V10.5更新说明1.修复拨号英文错误2.修复转送场景问题3.修复设置场景密码乱码问题4.修复前台批量删除客户图片5.修复数据收集分页问题6.修复图片分类错乱问题7.修复音乐和特效冲突问题8.修 ...

  6. 【krpano】加密XML手动解密分析

    krpano允许对XML文件进行加密,对XML进行相应的保护.加密分为两种,第一种为公共加密,即允许其他krpano全景读取该XML,而另一种为私有加密,仅允许加密的用户读取XML.两种加密方式的算法 ...

  7. .Net Core Linux centos7行—.net core json 配置文件

    .net core 对配置系统做出了大幅度更新,不在局限于之前的*.xml配置方式.现在支持json,xml,ini,in memory,环境变量等等.毫无疑问的是,现在的json配置文件是.net ...

  8. [.NET Core] 简单读取 json 配置文件

    简单读取 json 配置文件 背景 目前发现网上的 .NET Core 读取配置文件有点麻烦,自己想搞个简单点的. .NET Core 已经不使用之前的诸如 app.config 和 web.conf ...

  9. Asp .Net Core 读取appsettings.json配置文件

         Asp .Net Core 如何读取appsettings.json配置文件?最近也有学习到如何读取配置文件的,主要是通过 IConfiguration,以及在Program中初始化完成的. ...

随机推荐

  1. 题解-PKUWC2018 Slay the Spire

    Problem loj2538 Solution 在考场上当然要学会写暴力,考虑如果手上已经有了\(a\)张攻击牌和\(b\)张强化牌: 首先强化牌会在攻击牌之前用(废话),其次要将两种牌分别从大往小 ...

  2. cocos2dx 3.x 修改NDK_ROOT、ANDROID_SDK_ROOT、ANT_ROOT路径

    CMD到setup.py目录 Python setup.py -h 查看帮助: Options:  -h,--help            showthis help message and exi ...

  3. CANopen--实现双电机速度同步

    图1 将上图图中左边的电机和右边的电机进行速度同步,右边的电机同步左边的电机速度.这里需要知道Copley的驱动中的速度环的输入输出情况.如下图所示,速度环限制器接收速度命令信号,经限制后,产生一限制 ...

  4. [MySQL]理解关系型数据库4个事务隔离级别

    概述 SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的.低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销. 1. Read Uncommi ...

  5. 如何将代码通过vs2017加载到GitHub

    (1)登陆GitHub并注册账户,在用户中新建repository  (2)建立后,会给出新建repository地址,将其复制  (3)用VS新建一个项目,勾选“新建Git存储库”或者打开一个已经创 ...

  6. Android 常用正则表达式

    前言 闲扯一下,已经有好久没更新博客了,记得上一篇博客的更新时间为 2017-05-12 15:20.截止到今天,超过一百天没更新了. 这篇博客的内容大多数是从别的博客摘抄过来的,写这篇博客的目的主要 ...

  7. Vue项目构建开发笔记(vue-lic3.0构建的)

    1.router.js里面 { path: '/about', name: 'about', // route level code-splitting // this generates a sep ...

  8. Java jvisualvm 远程监控tomcatt

    第一步 在远程tomcat 的bin目录下的start.sh 文件中添加一些内容(添加在exec "$PRGDIR"/"$EXECUTABLE" start & ...

  9. R-CNN,SPP-NET, Fast-R-CNN,Faster-R-CNN, YOLO, SSD系列

    就是想保存下来,没有其他用意 原博文:http://blog.csdn.net/qq_26898461/article/details/53467968 3. 空间定位与检测     参考信息< ...

  10. NPOI打印设置

    打印设置主要包括方向设置.缩放.纸张设置.页边距等.NPOI 1.2支持大部分打印属性,能够让你轻松满足客户的打印需要. 方向设置首先是方向设置,Excel支持两种页面方向,即纵向和横向. 在NPOI ...