Js逆向--七麦网analysis加密

最近,偶然间看到一个这样的需求,需要在七麦网上逆向拿数据,所以我查看了一下,发现七麦网在请求时,都会在每个url后面新增一个 ?analysis=xxx 这样的键值对,显然这是经过加密的,所以这时候我的好奇心就既然出来了,决定研究研究他的加密方式。。

1、页面分析

打开七麦网,F12打开开发工具,随便查看一个请求,都可以看到确实每个请求url后都有一个经过加密的键值对


image.png

这个analysis是怎么来的呢?

第一步,按住Ctrl+F在开发工具栏搜索analysis,发现并没有找到相关的xxx.js文件处理analysis,那我们换个思路,这时候可以考虑跟踪请求调用栈,但是这样一个一个跟踪效率是很低的,所以点击第一个调用栈进入js文件


image.png

image.png

那怎么定位analysis相关的代码呢?这里我们可以借助XHR断点的方式来试试看,设置了断点后,只要代码运行过程中遇到url中包含有analysis相关的就会像DEBUG调式一样停下来


image.png

ok 刷新网页,发现断点打在了这个地方,右边Scope也看不出来什么异常


image.png

继续按着F10往下走调试,这个过程中要注意右侧Scope的值,随便放一个调试期间的截图,这时候还没相关的对analysis的处理,继续往下走


image.png

下面的图可以发现url上已经没有analysis的,说明可能要到了,继续往下走,这时候用单步调试F9就好


image.png

走到这步,右侧的Scope中发现有个字段e的值跟analysis后面跟着的值很像,显然到这里我们已经定位到了这个加密字符串产生的位置,它的主体代码就是左边圈出来的部分


image.png

第二步,打开一个可以运行js环境的工具,我这里使用的是pycharm,新建一个js文件,将上面的主体代码拷贝进去,用一个方法封装起来,参数是url


image.png

这里将一个知识点,(0, i[jt])这种形式,我们可以把它看作C语言中的逗号操作符,以最后的那位数的结果作为结果,因此可以改写成:args =i[qt](a, d),analysis=ijt

尝试运行看看,发现报错


image.png

那我们就去这个i对应的方法在哪里,鼠标移到i[jt]上,进入对应的方法,这里经过混淆,v才是i[jt]的实际方法


image.png

image.png

将整个v方法拷贝到我们的js文件,将i[jt]替换成v,为了防止后面的操作可能产生和v方法一样的变量名或者方法,我这里将v方法处理一下,然后替换,代码如下

function v(t) {
    t = z[V1](t)[T](/%([0-9A-F]{2})/g, function(n, t) {
        return o(Y1 + t)
    });
    try {
        return z[Q1](t)
    } catch (n) {
        return z[W1][K1](t)[U1](Z1)
    }
}
const obj = {}
obj.xx = v

function f1(url){
    // e = (0,i[jt])((0,
    //     i[qt])(a, d))
    e = obj.xx(i[qt](a,d))
}

url = "/index/banner"
console.log(f1(url))

在运行,还是报错


image.png

重复上面的方法,找到i对应的方法,拷贝到js,然后替换相应的i[qt]


image.png

运行报错 a is not defined
到主体代码附近找看看a相关的代码,将这些代码拷贝下来到js
image.png

分析一下a的组成
a : "Mjg=@#/index/banner@#40001143610@#3"
① Mjg= + ② @# + ③ /index/banner + ④ @# + ⑤ 40001143610 + ⑥ @# + ⑦ 3

① 先不看
②④⑥是相同的字符@#
③是url请求地址,可以知道f1方法需要传入的参数就是跟请求地址有关系了
⑤是一个11位的时间戳
⑦是一个单独的数字3
结合代码来看看哪些是固定的哪些是变化的

a = (a += v + t[Jt][T](t[Mt], _)) + (v + r) + (v + 3)

可以看到变量v固定是@#,结尾固定是数字3,所以我们可以自己定义一个变量v的值是@#


image.png

r的值是一个时间戳,在上面的代码中被赋值


image.png

image.png

那中间部分③对应的就是t[Jt][T](t[Mt], _))这块代码,结合上面改写一下变成这样
image.png

现在还剩下① 是怎么来的呢,我们将断点打在这行重新刷新网页一步步调试看看,调试过程中可能会多次进入到这个断点,要注意右侧url是不是对应的请求地址,我们以为上面那个请求地址为例
先对a赋值为[],然后继续走,走到框出来的代码的时候,发现a变成了[28]


image.png

可以知道a在经过下面这段代码的时候也经过了处理,将代码拷贝到js
运行报错 z is not defined ,z未定义


image.png

image.png

到网页代码中,鼠标移动到z看看是什么?可以看到,z是js自带的window对象,既然确实,那就补上,其实在js中window对象就是this

如果出现这样的代码zQ1,Q1的值是固定的字符串,比如"btoa",z为Window对象,可以改写成 zQ1 => btoa(t),z"encodeURIComponent" => encodeURIComponent(t)

image.png

运行 W is not defined
image.png

鼠标移到W,发现是个字符串,根据上面的说明new z[W] => new Date
继续运行,发现s未定义,重复上面的步骤,这里s的值是-314,不妨先固定写死在代码里,其实这里的s是动态变化的,但是对结果并没有影响
image.png

重复上面的步骤,将代码改写一下,变成这样
image.png

运行,发现t未定义,结合代码
image.png

发现这边t[Zt]取得值是请求参数params,那我们就在f1方法上再加一个参数
这里是return可能会影响代码继续往下执行,调整一下代码,f1方法变成这样
image.png

image.png

下面的代码看起来比较好理解,就是遍历params里的每个键值对,如果键是analysis就跳过,将其他键的值拼接成字符串


image.png

我们根据上面的操作,将 v(t)和h(n, t)的代码调整一下,如下


image.png

v(t)中的o的方法
image.png

改写一下


image.png

总的代码

function o(n) { //o是我们h中要o具体函数的实现
    t = "",
    ['66', '72', '6f', '6d', '43', '68', '61', '72', '43', '6f', '64', '65']['forEach'](function(n) {
        t += unescape("%u00" + n)
    });
    var t, e = t;
    return String[e](n)
}
function v(t) {
    t = encodeURIComponent(t)["replace"](/%([0-9A-F]{2})/g, function(n, t) {
        return o("0x" + t)
    });
    try {
        return btoa(t)
    } catch (n) {
        return Buffer["from"](t)["toString"]("base64")
    }
}
const obj = {}
obj.xx = v

function h(n, t) {
    t = t || u();
    for (var e = (n = n["split"](""))["length"], r = t["length"], a = "charCodeAt", i = 0; i < e; i++)
        n[i] = o(n[i][a](0) ^ t[(i + 10) % r][a](0));
    return n["join"]("")
}

function f1(url,params){
    var v = "@#"
    var s = -314
    var H = 0
    var e, r = +new Date - (s || H) - 1661224081041, a = [];
    var d = "xyz517cda96efgh"
    if(void 0 !== params && (params !== {})){
        Object["keys"](params)["forEach"](function(n) {
            if (n == "analysis")
                return false;
            params["hasOwnProperty"](n) && a["push"](params[n])
        })
    }
    //a :  "Mjg=@#/index/banner@#40001143610@#3"
    a = a["sort"]()["join"]("")
    a = obj.xx(a)
    a = (a += v + url + (v + r) + (v + 3))

    // e = (0,i[jt])((0,
    //     i[qt])(a, d))
    e = obj.xx(h(a,d))
    return e
}

url = "/index/banner"
params = {
    'cid' : 28
}
console.log(f1(url))

运行,大家可以自行去验证一下


image.png

如果运行过程发现ATOB 或者BTOA IS NOT DEFINED的问题,在js前加上以下这段

// =====================================================================
// atob 或者btoa 方法是浏览器实现的而非 js 自带,需要需要使用这两个方法需要自己实现  最前面加上这段js 就可以使用了
// 用来解决ATOB 或者BTOA IS NOT DEFINED的问题
global.Buffer = global.Buffer || require('buffer').Buffer;

if (typeof btoa === 'undefined') {
    global.btoa = function (str) {
        return new Buffer.from(str, "binary").toString('base64');
    };
}
if (typeof atob === 'undefined') {
    global.atob = function (b64Encoded) {
        return new Buffer.from(b64Encoded, 'base64').toString("binary");
    };
}

(function(a) {
    var a = atob(a);
    var b = [];
    for (var i = 0; i < 32; i++) {
        b.push(a[i].charCodeAt())
    }
    var c = [];
    for (var i = 0; i < 16; i++) {
        c.push(0)
    }
    var d = (b[0] % 8) * 2 - 1;
    if (d < 0) {
        d = 5
    }
    for (var i = 0; i < 16; i++) {
        var j = (((i + 1) % 16) * d) % 16;
        c[j] = b[i] ^ b[16 + i]
    }
    var a = '';
    for (var i = 0; i < 16; i++) {
        a += String.fromCharCode(c[i])
    }
    console.log(btoa(a))
}
)("SZZ0XDbSPf3OdgwIM2axNScLRZjRvmgmcr7S6J/d9dA=");
// =====================================================================
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,042评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,996评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,674评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,340评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,404评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,749评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,902评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,662评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,110评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,577评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,258评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,848评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,726评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,952评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,271评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,452评论 2 348

推荐阅读更多精彩内容