逆向研究笔记1

我做的是爬取某窝机票请求体字段的研究并逆向
我们要爬取的就是这个网站:aHR0cHMlM0EvL3d3dy5tYWZlbmd3by5jbg==的飞机票板块
首先贴图,研究成果:

ggemain 加密_ggemain 加密

如图:马蜂窝机票的列表页请求体中有三个加密字段sign,signkey,tfb_req_id

ggemain 加密_全局搜索_02

使用快捷键:ctar+F启用查找功能把这三个加密的参数的随意一个复制到查找中点击刷新进行搜索发现为未找到匹配项,可以断定这些参数不是接口生成的透传到本接口的,那么大概率就是js中进行加密的字段了(还有个思路便是在元素页面中全局搜索这个值)

ggemain 加密_ggemain 加密_03

如下图,点击搜索 进行全局搜索

ggemain 加密_ggemain 加密_04

把其中一个key输入搜索框中并,点击搜索,下图中的结果是便是加密参数的js文件了

ggemain 加密_搜索_05

打开文件后,全文搜索signKey参数,发现有5个,看着很多,但我们只要其中一个,

ggemain 加密_python_06


在5个参数位置都打上断点,并点击页面中的日期,在选择航班的页面中点击日期进行翻页,进而触发js的调用,断点断住的地方,那这就是我们要找的加密位置了

ggemain 加密_ggemain 加密_07


由于源码中signkey传的值为s所以我们在4575行 打上断点,断住后可以看到l.default 是一个方法,点击index链接进入该方法

ggemain 加密_全局搜索_08

可以看到进入了e.default的方法,这个方法中直接就return方法返回了a.randomGuid

ggemain 加密_字段_09

在a.randomGuid打上断点并在下图右侧的断点栏里取消上一步骤的断点

ggemain 加密_ggemain 加密_10

如下图在断点后,可以看到a.randomGuid也是个方法,通过vendor进入方法

ggemain 加密_ggemain 加密_11


如下图,进入了新的js文件里,可以看到停在了e.default的方法上,而这个方法的返回值调用的则是上放的r方法

ggemain 加密_字段_12

到此e方法调用介绍,然我们看看返回的r(!1, t) + r(!0, t) + r(!0, t) + r(!1, t) 是否为我们想要的值

ggemain 加密_全局搜索_13


复制r(!1, t) + r(!0, t) + r(!0, t) + r(!1, t) 在控制台中粘贴并敲击回车返回了一串字符串,而且该字符长度与请求接口的key值signKey的vlaue值相等,那么就可以判断加密的方法就是这里了

ggemain 加密_搜索_14

那么先把该方法抠出来与本地的js文件中进行处理

ggemain 加密_全局搜索_15

这是处理完后的js,因为最外圈方法的(t, e, n)没有被调用,且中间的Object同样也没有被调用所以在js中进行去除处理,现在e方法就是最后调用的方法了,那么就无需在写为e.default == function,重命名为signkey,在本地调用

ggemain 加密_搜索_16

结果只返回了方法名,难道js处理的改失败了?

别急啊,别忘了,上一个调用signkey的方法是带有参数的,虽然是个双引号

ggemain 加密_字段_17


这里在加入参数后便有了返回值

ggemain 加密_python_18

到了这一步,我们返回到首个断点的地方,在此观察,发现我们只完成了l.default的生成,而s的值是(0, l.default),所以本地的js还要在调整一下

ggemain 加密_ggemain 加密_19


这样我们便获取了一个参数的加密值

ggemain 加密_全局搜索_20

现在我们再来看sign的值

ggemain 加密_ggemain 加密_21


可以看出sign的值与signkey的值大致相同,只不过参数不为空了,那么接下来在此对sign打上断点

ggemain 加密_全局搜索_22


ggemain 加密_ggemain 加密_23

ggemain 加密_搜索_24


ggemain 加密_字段_25


ggemain 加密_python_26


以上5张图便是sign加密的所有参数了,只不过被拼凑到了一起

现在开始逆向sign如下图点击index,进入d.default方法

ggemain 加密_ggemain 加密_27


ggemain 加密_全局搜索_28

对g()方法今天按步调试,可以看到t就是上方5图参数拼凑成的,而e,i两个参数则为undefined

ggemain 加密_搜索_29


通过调试发现这些方法都在同一个function中那么把这一块代码全部复制出来,并进行处理

ggemain 加密_字段_30


如下图,便是function里全部方法了,其中r方法有重复由于sign的参数重听到了signkey的参数所以便写在了一起调试修改一下signkey的方法名把第一行的r方法改成了r123,同理signkey方法的return 的r也需要改

ggemain 加密_python_31

这里我们打印g方法,看看结果,首先复制刚刚页面上生成的t值’SHACAN95409e1c9b74304558a116ad606231472022-08-1295409e1c9b74304558a116ad60623147’ ,运行js的代码

ggemain 加密_全局搜索_32

结果便出来了,但是目前sign的加密参数还未完成,先前调用signkey的方法,每调用一次都返回不同的值,所以我们要对t的传参进行修改,

ggemain 加密_全局搜索_33

ggemain 加密_搜索_34

现在进入第三个字段的加密方法
老方法,按照步骤,找到加密点,熟悉的i.default 空的传参,断点并通过i.default进入方法

ggemain 加密_python_35


看到这些值,那么499行的加密方法便是tfb_req_id的加密了

ggemain 加密_全局搜索_36


芜湖,又是熟悉的面孔,这不就是signkey的加密方法吗,看来只是换了个马甲,有调了一次加密所以生成了不同的值

ggemain 加密_python_37

现在让我们用python来请求这个接口来确认我们的逆向是否成功

废话不多说,上代码,

运行js脚本获取三个加密参数值,并放入python脚本中

ggemain 加密_搜索_38

到此请求成功,但是list为空,这是怎么回事呢?

ggemain 加密_python_39

且看:这是该网站的机制之一,这里指进行逆向方面的研究,不进行爬虫,所以此处变不进行研究了

ggemain 加密_字段_40

//抠下来的加密算法
function r123(t) {
    var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : "-"
      , n = (Math.random().toString(16) + "000000000").substr(2, 8);
    return t ? e + n.substr(0, 4) + e + n.substr(4, 4) : n
}
function signkey() {
    var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "-";
    return r123(!1, t) + r123(!0, t) + r123(!0, t) + r123(!1, t)
};

function s(t, e) {
    var i = (65535 & t) + (65535 & e);
    return (t >> 16) + (e >> 16) + (i >> 16) << 16 | 65535 & i
}
function r(t, e, i, a, r, n) {
    return s(function(t, e) {
        return t << e | t >>> 32 - e
    }(s(s(e, t), s(a, n)), r), i)
}
function n(t, e, i, a, s, n, o) {
    return r(e & i | ~e & a, t, e, s, n, o)
}
function o(t, e, i, a, s, n, o) {
    return r(e & a | i & ~a, t, e, s, n, o)
}
function c(t, e, i, a, s, n, o) {
    return r(e ^ i ^ a, t, e, s, n, o)
}
function l(t, e, i, a, s, n, o) {
    return r(i ^ (e | ~a), t, e, s, n, o)
}
function d(t, e) {
    var i, a, r, d, u;
    t[e >> 5] |= 128 << e % 32,
    t[14 + (e + 64 >>> 9 << 4)] = e;
    var p = 1732584193
      , f = -271733879
      , h = -1732584194
      , m = 271733878;
    for (i = 0; i < t.length; i += 16)
        a = p,
        r = f,
        d = h,
        u = m,
        f = l(f = l(f = l(f = l(f = c(f = c(f = c(f = c(f = o(f = o(f = o(f = o(f = n(f = n(f = n(f = n(f, h = n(h, m = n(m, p = n(p, f, h, m, t[i], 7, -680876936), f, h, t[i + 1], 12, -389564586), p, f, t[i + 2], 17, 606105819), m, p, t[i + 3], 22, -1044525330), h = n(h, m = n(m, p = n(p, f, h, m, t[i + 4], 7, -176418897), f, h, t[i + 5], 12, 1200080426), p, f, t[i + 6], 17, -1473231341), m, p, t[i + 7], 22, -45705983), h = n(h, m = n(m, p = n(p, f, h, m, t[i + 8], 7, 1770035416), f, h, t[i + 9], 12, -1958414417), p, f, t[i + 10], 17, -42063), m, p, t[i + 11], 22, -1990404162), h = n(h, m = n(m, p = n(p, f, h, m, t[i + 12], 7, 1804603682), f, h, t[i + 13], 12, -40341101), p, f, t[i + 14], 17, -1502002290), m, p, t[i + 15], 22, 1236535329), h = o(h, m = o(m, p = o(p, f, h, m, t[i + 1], 5, -165796510), f, h, t[i + 6], 9, -1069501632), p, f, t[i + 11], 14, 643717713), m, p, t[i], 20, -373897302), h = o(h, m = o(m, p = o(p, f, h, m, t[i + 5], 5, -701558691), f, h, t[i + 10], 9, 38016083), p, f, t[i + 15], 14, -660478335), m, p, t[i + 4], 20, -405537848), h = o(h, m = o(m, p = o(p, f, h, m, t[i + 9], 5, 568446438), f, h, t[i + 14], 9, -1019803690), p, f, t[i + 3], 14, -187363961), m, p, t[i + 8], 20, 1163531501), h = o(h, m = o(m, p = o(p, f, h, m, t[i + 13], 5, -1444681467), f, h, t[i + 2], 9, -51403784), p, f, t[i + 7], 14, 1735328473), m, p, t[i + 12], 20, -1926607734), h = c(h, m = c(m, p = c(p, f, h, m, t[i + 5], 4, -378558), f, h, t[i + 8], 11, -2022574463), p, f, t[i + 11], 16, 1839030562), m, p, t[i + 14], 23, -35309556), h = c(h, m = c(m, p = c(p, f, h, m, t[i + 1], 4, -1530992060), f, h, t[i + 4], 11, 1272893353), p, f, t[i + 7], 16, -155497632), m, p, t[i + 10], 23, -1094730640), h = c(h, m = c(m, p = c(p, f, h, m, t[i + 13], 4, 681279174), f, h, t[i], 11, -358537222), p, f, t[i + 3], 16, -722521979), m, p, t[i + 6], 23, 76029189), h = c(h, m = c(m, p = c(p, f, h, m, t[i + 9], 4, -640364487), f, h, t[i + 12], 11, -421815835), p, f, t[i + 15], 16, 530742520), m, p, t[i + 2], 23, -995338651), h = l(h, m = l(m, p = l(p, f, h, m, t[i], 6, -198630844), f, h, t[i + 7], 10, 1126891415), p, f, t[i + 14], 15, -1416354905), m, p, t[i + 5], 21, -57434055), h = l(h, m = l(m, p = l(p, f, h, m, t[i + 12], 6, 1700485571), f, h, t[i + 3], 10, -1894986606), p, f, t[i + 10], 15, -1051523), m, p, t[i + 1], 21, -2054922799), h = l(h, m = l(m, p = l(p, f, h, m, t[i + 8], 6, 1873313359), f, h, t[i + 15], 10, -30611744), p, f, t[i + 6], 15, -1560198380), m, p, t[i + 13], 21, 1309151649), h = l(h, m = l(m, p = l(p, f, h, m, t[i + 4], 6, -145523070), f, h, t[i + 11], 10, -1120210379), p, f, t[i + 2], 15, 718787259), m, p, t[i + 9], 21, -343485551),
        p = s(p, a),
        f = s(f, r),
        h = s(h, d),
        m = s(m, u);
    return [p, f, h, m]
}
function u(t) {
    var e, i = "", a = 32 * t.length;
    for (e = 0; e < a; e += 8)
        i += String.fromCharCode(t[e >> 5] >>> e % 32 & 255);
    return i
}
function p(t) {
    var e, i = [];
    for (i[(t.length >> 2) - 1] = void 0,
    e = 0; e < i.length; e += 1)
        i[e] = 0;
    var a = 8 * t.length;
    for (e = 0; e < a; e += 8)
        i[e >> 5] |= (255 & t.charCodeAt(e / 8)) << e % 32;
    return i
}
function f(t) {
    var e, i, a = "";
    for (i = 0; i < t.length; i += 1)
        e = t.charCodeAt(i),
        a += "0123456789abcdef".charAt(e >>> 4 & 15) + "0123456789abcdef".charAt(15 & e);
    return a
}
function h(t) {
    return unescape(encodeURIComponent(t))
}
function m(t) {
    return function(t) {
        return u(d(p(t), 8 * t.length))
    }(h(t))
}
function v(t, e) {
    return function(t, e) {
        var i, a, s = p(t), r = [], n = [];
        for (r[15] = n[15] = void 0,
        s.length > 16 && (s = d(s, 8 * t.length)),
        i = 0; i < 16; i += 1)
            r[i] = 909522486 ^ s[i],
            n[i] = 1549556828 ^ s[i];
        return a = d(r.concat(p(e)), 512 + 8 * e.length),
        u(d(n.concat(a), 640))
    }(h(t), h(e))
}
function g(t, e, i) {
    return e ? i ? v(e, t) : function(t, e) {
        return f(v(t, e))
    }(e, t) : i ? m(t) : function(t) {
        return f(m(t))
    }(t)
}

sign_key = (0,signkey(""));
console.log(sign_key);

text = ("" + "SHA" + "CAN" + sign_key + "2022-08-12" + "" + sign_key);
console.log((0 , g(text)));

sign_key = (0,signkey(""));
console.log(sign_key);

好了,以上便是对马蜂窝网站机票的加密研究了,本篇文章讲解到这里啦,我感觉我讲的还算细致吧,我肯定有讲的不好的地方,欢迎各位大佬来指正我 。

我也在不断的学习中,学到新东西第一时间会跟大家分享
大家可以动动小手,点波关注不迷路。

如果关于本篇文章有不懂的地方,欢迎大家下面留言,我知道的都会给大家一 一解答。