js逆向分析实战之七麦数据
1.介绍:
要分析的网站是:https://www.qimai.cn/rank
①当你打开网站,打开控制台的时候,网站有debugger检测,会陷入一个死循环,让你无法调试,如下图:
②在解决掉debugger问题后(稍后介绍如何解决),点击到你想爬取的数据页面如:https://www.qimai.cn/rank/index/brand/paid/device/iphone/country/cn/genre/36/date/2018-11-11 查看ajax请求,你会看到你想要的数据,but每个重要请求都会有个analysis字段,此字段便是本文的重点分析对象。如下图:
下面正式介绍如何解决检测deugger及其analysis的逆向分析
2.准备工具:
抓包工具:fiddler、charles
浏览器:firefox、chrome
工具凭个人喜好选择
3.解决debugger检测:
①回到本文第一张图片,查看黄色框部分。查看堆栈,点击anonymous下的e,跳转到了app.xxxxxxx.js文件的debugger执行函数位置了,如下图:
②分析下var a = [ 'r','e', 'g','g', 'u', 'b','e', 'd'].reverse().join('');
这个变量a不就是“debugger”嘛,往下继续自动执行递归函数e调用debugger,造成了无法让我们正常调试。
③ok!我们已经知道是哪个函数在搞的鬼了,也知道这个函数在哪个文件了。下边我们改如何注释掉这段函数呢?我的解决办法是抓包!关于抓包工具如何使用这里就不介绍了,不会的同学请自行百度“抓包https”
打开抓包工具,拦截app.xxxxxx.js文件注释掉以下代码块
!function e(n) { (1 !== ('' + n / n).length || 0 === n) && function () { }.constructor(a) (), e(++n) }(0)
如下图:
已经可以正常调试了
4.analysis逆向分析:
经过以上步骤已经可以正常调试了,下边我们讲下我的分析思路。
①定位analysis字段的生成位置(这一步有很多方法)
我的第一反应是全项目搜索,command+shift+f(mac版本firefox控制台快捷键) 搜索“analysis”,然而并没有搜到想要的结果。
尝试第二种办法,添加xhr断点,关键词api,即api.qimai.cn中的api,刷新网页。如下图:
分析下代码h为XMLHttpRequest对象,便是发出请求的最后一步,然后看下图右侧红框堆栈部分,如下图:
自上而下点击堆栈开始做断点吧,看看哪部分代码块有自己想要的线索。
花费好长时间,最终在get堆栈定位到app.xxxxx.js文件的以下位置,找到了“analysis",继续断点得出r便是analysis的值。r由两个函数l.d和l.h处理o后得出
②解决变量o
分析下代码:这个变量o初始值不就是url的参数值然后做了个排序,然后拼成的字符串嘛,如上图url:
www.qimai.cn/rank/marketRank/market/3/category/-2/country/cn/collection/topselling_free/date/2018-11-13----->[3,-2,cn,topselling_free,2018-11-13],
然后做了个排序拼接在一起就是-22018-11-113cntopselling_free,这里经过一个l.d函数,让我们看下这个函数做了什么事,选中l.d进去h(a)函数:
function h(a) {return x()(encodeURIComponent(a).replace(/%([0-9A-F]{2})/g, function(a, e) {return r("0x" + e)}))}
又出来个x(),继续步进,到了下图位置,下图命名为图1
t就是上述的o,也就是url参数;
console下e.from(t.toString(),“binary”)获得了一个数组, 赋值给了n
n.toSting(‘base64’)即是加密后的o
下面我们看看七脉是如何给o进行加密的
首先我们先看看是如何获得的数组,先进入e.from函数,又到s函数,参数依然是url的参数,这网站弄的真够绕的,下图命名为图2
继续进入s函数,传参url参数,下图命名为图3:
分析下上图中f函数参数,重点来了!!!!!!!
t=null,
e=url参数
n=“binary”,
函数o(t,r)生成了一个长度和url参数等长度且全部为0的数组,并赋值给t
继续进入t.write(e,n)
下图命名为图4
继续write函数调用k函数,进入k函数传参t=url参数,e=“binary”, n =undefined!
下图命名为图5
k调C,C调K(W(e)),console下W(e)得到了数组,这个数组就是图1中出现的数组!!!!继续步进进入W看看url参数怎么转成数组的,下图命名为图6
function W(t) {for (var e = [], n = 0; n < t.length; ++n)e.push(255 & t.charCodeAt(n));return e}
遍历t,获取每个下标元素对应的 ASCII 数值,然后和255进行&运算。charCodeAt 和python中ord函数作用相同
ok!步出!步进看K函数如何将W得到的数组进行加密的
下图命名为图7
K函数并没有对此数组进行操作,return i; i的数值和e相同!!
至此我们得到了图1中的数组,将数组进行一个toString(‘base64’)操作即是加密结果
如果至此你已经蒙圈了,可以将断点打到图一中的n.toString(‘base64’),为了防止其他断点的干预,我习惯将其他断点先关闭,然后刷新,重新看数组如何变成base64的。
如果你还很清楚,那直接步出步出步出。。。,到图1所示代码块,如下状态
继续步进
进入到M
console下Q.fromByteArray(t),即是加密后的o,进入到fromByteArray
以下函数是对数组加密,即生成base64字符串的过程,直接调用u即可
//对数组进行加密function u(t) { //用到了sfor (var e, n = t.length, r = n % 3, i = "", o = [], a = 16383, u = 0, c = n - r; u < c; u += a)o.push(s(t, u, u + a > c ? c : u + a));return 1 === r ? (e = t[n - 1],i += l[e >> 2],i += l[e << 4 & 63],i += "==") : 2 === r && (e = (t[n - 2] << 8) + t[n - 1],i += l[e >> 10],i += l[e >> 4 & 63],i += l[e << 2 & 63],i += "="),o.push(i),o.join("")}function s(t, e, n) { //用到了afor (var r, i = [], o = e; o < n; o += 3) r = (t[o] << 16 & 16711680) + (t[o + 1] << 8 & 65280) + (255 & t[o + 2]),i.push(a(r));return i.join('')}function a(t) { //用到了lreturn l[t >> 18 & 63] + l[t >> 12 & 63] + l[t >> 6 & 63] + l[63 & t]
}//l就是A-Za-z0-9+ 生成l
for (var l = [], c = [], f = 'undefined' != typeof Uint8Array ? Uint8Array : Array, d = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', h = 0, p = d.length; h < p; ++h) l[h] = d[h],c[d.charCodeAt(h)] = h;
c['-'.charCodeAt(0)] = 62,c['_'.charCodeAt(0)] = 63
综合W函数得到以下js
命名为qimai.js
经过u函数后,便拿到了加密后的o了,剩下的分析便大同小异了,没什么难度了。
function W(t) {//t为排序后url参数值,返回数组t = t.toString()for (var e = [], n = 0; n < t.length; ++n) e.push(255 & t.charCodeAt(n));return e
}//u函数将数组转化为base64
for (var l = [], c = [], f = 'undefined' != typeof Uint8Array ? Uint8Array : Array, d = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', h = 0, p = d.length; h < p; ++h) l[h] = d[h],c[d.charCodeAt(h)] = h;
c['-'.charCodeAt(0)] = 62,c['_'.charCodeAt(0)] = 63function a(t) {return l[t >> 18 & 63] + l[t >> 12 & 63] + l[t >> 6 & 63] + l[63 & t]
}function s(t, e, n) {for (var r, i = [], o = e; o < n; o += 3) r = (t[o] << 16 & 16711680) + (t[o + 1] << 8 & 65280) + (255 & t[o + 2]),i.push(a(r));return i.join('')
}function u(t) {for (var e, n = t.length, r = n % 3, i = '', o = [], a = 16383, u = 0, c = n - r; u < c; u += a) o.push(s(t, u, u + a > c ? c : u + a));return 1 === r ? (e = t[n - 1], i += l[e >> 2], i += l[e << 4 & 63], i += '==') : 2 === r && (e = (t[n - 2] << 8) + t[n - 1], i += l[e >> 10], i += l[e >> 4 & 63], i += l[e << 2 & 63], i += '='),o.push(i),o.join('')
}//直接传入排序后的url参数值,返回base64
function decrypt(o) {return u(W(o))
}
下边附上Python完整版本Demo
import execjs
import timeclass Decrypt():def __init__(self):js_path = ’qimai.js' #上述的qimai.jsf = open(js_path)js = f.read()self.ctx = execjs.compile(js)f.close()def __f(self, a):'''解密第一步:param a::return:'''e = 'a12c0fa6ab9119bc90e4ac7700796a53'a = list(a)for i in range(len(a)):a[i] = chr(ord(a[i]) ^ ord(e[i % len(e)]))return ''.join(a)@classmethoddef decrypt(cls, tags, params={}):''':param tags: url的分类 如应用宝页面 https://www.qimai.cn/rank/marketRank 则传入rank/marketRank:return:'''self = cls()now_date = round(time.time() * 1000)t = now_date - 708 - 1515125653845params_ = ''if params:o_ = ''.join(sorted(list(params.values())))params_ = self.ctx.call('decrypt', o_)o = '%s@#/%s@#%s@#1' % (params_, tags, t)s = self.__f(o)analysis = self.ctx.call('decrypt', s)return analysisif __name__ == '__main__':now_date = time.strftime('%Y-%m-%d', time.localtime())params_list = [('rank/marketRank', {'market': '1', 'category': '6', 'date': now_date}, '360'),('rank/marketRank', {'market': '3', 'category': '-2', 'date': now_date}, '应用宝'),('rank/marketRank', {'market': '5', 'category': '5', 'date': now_date}, '豌豆荚'),('rank/marketRank', {'market': '4', 'category': '6', 'date': now_date}, '小米'),('rank/marketRank', {'market': '7', 'category': '7', 'date': now_date}, '魅族'),('rank/marketRank', {'market': '9', 'category': '4', 'date': now_date}, 'oppo'),('rank/release', {'genre': '36', 'date': now_date}, 'App Store')]for tags, params, store in params_list:analysis = Decrypt.decrypt(tags, params)print(analysis)
明天附上github
js逆向分析实战之七麦数据相关推荐
- 最新战火互娱JS逆向分析实战教程
目标网址:https://passport.kongzhong.com/ 重要说明:文章教程仅供参考学习,请勿用于非法用途,否则后果自负. 目录 一.接口参数分析
- 最新中烟新商盟JS逆向分析实战教程
目标网址:https://xinshangmeng.com/ 重要说明:文章教程仅供参考学习,请勿用于非法用途,否则后果自负. 目录 一.接口参数分析 二.全局搜索j_mcmm关键词</
- JS逆向分析新浪某站登录处RSA加密
文章目录 前言 RSA加解密 核心思想 Pyhon实现 NoPadding 新浪网实战 JS加密分析 JS函数调试 Py调用脚本 BurCrypto爆破 插件介绍 实战案例 总结 前言 在渗透测试过程 ...
- Linux Security Module逆向分析实战
Linux Security Module逆向分析实战 本文记录了对某发行版Linux中一个安全模块(LSM)的逆向过程,该LSM对系统中待运行的程序进行安全校验,数据流穿越内核态与用户态,涉及系统内 ...
- 轻JS逆向分析“攒经验”项目之某交易所Sign加密参数逆向分析
最近忙着在搞大数据相关的东西,没什么太多时间去研究复杂的JS,所以给大家来几个练手的网站"攒攒经验"吧!这次出的系列是<轻JS逆向分析"攒经验"项目> ...
- JS逆向 -- 分析某站aid、cid、w_rid和sid的加密过程
接上节课内容 JS逆向 -- 分析某站buvid3和_uuid的加密过程 JS逆向 -- 分析某站b_lsid值加密过程 一.清除cookie信息,刷新网页,ctrl+f搜索sid,这样找到的数据是在 ...
- QAX答题页面js逆向分析(二)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.通过前端js解密,获取答案 二.通过Python,模拟请求完成自登录到答题的所有操作. 1.引入库 2. 程序结构 ...
- R语言时间序列(time series)分析实战:时序数据加载、绘制时间序列图
R语言时间序列(time series)分析实战:时序数据加载.绘制时间序列图 目录
- js aes加密_某高考咨询网js逆向分析笔记
一.某高考资讯网逆向分析 某网站的js加密分析,安全签名signsafe + HmacSHA1 + AES 一年前分析过网站数据还没有加密,最近需要获取新的数据发现原先的爬虫失效,请求和响应都经过加密 ...
最新文章
- (转)一个as3写的减速效果
- 关系型数据库的ACID规则
- 这是时间的推移 不是系统的分类
- CRF++使用简介(windows下非接口)
- C语言深度剖析书籍学习记录 第三章 预处理
- 第三章 熟悉常用的HDFS操作
- 这就是即将发布的苹果刘海屏MacBook Pro样机?
- Mac更新之后使用终端提示:The default interactive shell is now zsh.
- SPIRE.DOC - .NET开发者的福利
- 720. 词典中最长的单词
- leetcode Largest Rectangle in Histogram 单调栈
- Python入门学习三
- python颜色识别,46行代码实现865种颜色识别,看过的都说顶呱呱!
- 如何解决back order中,confirmed qty can't be change的问题
- HDMI EDID详细解析
- linux 无线网卡 频段,Linux 网卡配置 (频段、发射功率等)
- c语言中千分号的用法,在ChemDraw中输入千分号的教程
- 日语动词+动词类型+动词活用
- 跟这台计算机连接的一个USB设备运行不正常,Windows无法识别
- xgboost的调优