思古解析js静态逆向分析

1.Fiddler抓包初步分析

在这里插入图片描述
一个方框就是我们请求的地址,然后发起了第二个方框的请求,这里的参数是没有变化的,就是换了一个接口,然后第二个方框里面发起了一个https://jx.sigujx.com/sigu_jx.php 的post的请求,也就是第三个方框,这个post了5个加密的参数,这就是我们后面需要分析的内容。
然后这个接口返回了一个加密的url,解密后应该就是第四个方框的请求,这里返回的还只是一个网址,并不是m3u8,然后这里面又发起了一个请求,就是第五个方框,这个就是m3u8了,还是一个加密的m3u8,那么下面就是一步一步分析请求参数的逻辑

2.请求接口参数分析

在这里插入图片描述
第二个方框返回的源代码中,可以看到有post请求的逻辑,这里的参数都给出来了

{"url":url,"key":sigu("070ea6cb655dd2ee4e07a68bfef84c9a"),"key2":sigu2("2110362178631681"),"key3":sigu3(key3),"token":token,"type":""},
参数来源
url全局中url变量的值
key由已知参数经过sigu函数得到
key2由已知参数经过sigu2函数得到
key3由key3参数经过sigu3函数得到
token全局中token变量的值
type空值

再看看源代码中有一段混淆很可疑,先进行反混淆
在这里插入图片描述
解密由https://www.qtool.net/decode网站提供的aaencode解密
在这里插入图片描述

这里就可以得到token了,在混淆的最后发现了

var url = $('#sigu_url').val();

这里可以看到是区网页仲id为sigu_url的值作为url的值,网页中可以很简单的找到
在这里插入图片描述

接下来还剩下三个方法体和一个参数,继续看看源代码的前面还引用了很多外部的js文件,全部都看一看,这里我直接说重要的地方,一个"/js/jquery.mim.js?20200731"下的js文件,里面的代码被混淆了

在这里插入图片描述

解密由网站http://tool.yuanrenxue.com/decode_obfuscator提供的ob混淆专解测试版V0.1

var _0x17e055 = function () {
  var _0x295a3f = true;
  return function (_0x29f3d0, _0x1024b0) {
    var _0x5e6290 = _0x295a3f ? function () {
      if (_0x1024b0) {
        var _0x28256a = _0x1024b0["apply"](_0x29f3d0, arguments);

        _0x1024b0 = null;
        return _0x28256a;
      }
    } : function () {};

    _0x295a3f = false;
    return _0x5e6290;
  };
}();

var _0x3763d7 = _0x17e055(this, function () {
  var _0x7e1c73 = typeof window !== "undefined" ? window : typeof process === "object" && typeof require === "function" && typeof global === "object" ? global : this;

  var _0x3cbfe2 = [[0, 0, 0, 0, 0], ["qjxS.sihygfujxM.GcKFAowm;CjCeVEx.w1Gk2S6bKcVJ.cn;AvaJpi.12H6c.WRcntJKHRYUTLePIyYUWJHfFEBfEZEUykIHIGSyDvqHJvtJMeUXGrwFVTPGEwrEUwJ"["replace"](new RegExp("[qShyfMGKFAwCCeVEwGkSbKVJAvJHWRtJKHRYUTLePIyYUWJHfFEBfEZEUykIHIGSyDvqHJvtJMeUXGrwFVTPGEwrEUwJ]", "g"), "")["split"](";"), false], [function (_0x7a5d57, _0x14ff0a, _0x4b32a2) {
    return _0x7a5d57["charCodeAt"](_0x14ff0a) == _0x4b32a2;
  }, function (_0x4400eb, _0x2c8bb7, _0x3fd447) {
    _0x3cbfe2[_0x4400eb][_0x2c8bb7] = _0x3fd447;
  }, function () {
    return true;
  }]];

  var _0x51d324 = function () {
    while (_0x3cbfe2[2][2]()) {
      _0x7e1c73[_0x3cbfe2[0][0]][_0x3cbfe2[0][2]][_0x3cbfe2[0][4]] = _0x7e1c73[_0x3cbfe2[0][0]][_0x3cbfe2[0][2]][_0x3cbfe2[0][4]];
    }
  };

  for (var _0x37e23a in _0x7e1c73) {
    if (_0x37e23a["length"] == 8 && _0x3cbfe2[2][0](_0x37e23a, 7, 116) && _0x3cbfe2[2][0](_0x37e23a, 5, 101) && _0x3cbfe2[2][0](_0x37e23a, 3, 117) && _0x3cbfe2[2][0](_0x37e23a, 0, 100)) {
      _0x3cbfe2[2][1](0, 0, _0x37e23a);

      break;
    }
  }

  for (var _0x2efca2 in _0x7e1c73[_0x3cbfe2[0][0]]) {
    if (_0x2efca2["length"] == 6 && _0x3cbfe2[2][0](_0x2efca2, 5, 110) && _0x3cbfe2[2][0](_0x2efca2, 0, 100)) {
      _0x3cbfe2[2][1](0, 1, _0x2efca2);

      break;
    }
  }

  for (var _0x386f6e in _0x7e1c73[_0x3cbfe2[0][0]]) {
    if (_0x386f6e["length"] == 8 && _0x3cbfe2[2][0](_0x386f6e, 7, 110) && _0x3cbfe2[2][0](_0x386f6e, 0, 108)) {
      _0x3cbfe2[2][1](0, 2, _0x386f6e);

      break;
    }
  }

  for (var _0x41a819 in _0x7e1c73[_0x3cbfe2[0][0]][_0x3cbfe2[0][2]]) {
    if (_0x41a819["length"] == 4 && _0x3cbfe2[2][0](_0x41a819, 3, 102)) {
      _0x3cbfe2[2][1](0, 4, _0x41a819);
    } else {
      if (_0x41a819["length"] == 8 && _0x3cbfe2[2][0](_0x41a819, 7, 101) && _0x3cbfe2[2][0](_0x41a819, 0, 104)) {
        _0x3cbfe2[2][1](0, 3, _0x41a819);
      }
    }
  }

  if (!_0x3cbfe2[0][0] || !_0x7e1c73[_0x3cbfe2[0][0]]) {
    return;
  }

  var _0xb48a00 = _0x7e1c73[_0x3cbfe2[0][0]][_0x3cbfe2[0][1]];

  var _0x5ec83e = !!_0x7e1c73[_0x3cbfe2[0][0]][_0x3cbfe2[0][2]] && _0x7e1c73[_0x3cbfe2[0][0]][_0x3cbfe2[0][2]][_0x3cbfe2[0][3]];

  var _0xf19686 = _0xb48a00 || _0x5ec83e;

  if (!_0xf19686) {
    return;
  }

  _0x2fe93e: for (var _0x575199 = 0; _0x575199 < _0x3cbfe2[1][0]["length"]; _0x575199++) {
    var _0x7c0a25 = _0x3cbfe2[1][0][_0x575199];

    var _0x1b9ad5 = _0xf19686["length"] - _0x7c0a25["length"];

    var _0x4f0dcd = _0xf19686["indexOf"](_0x7c0a25, _0x1b9ad5);

    var _0x5e4976 = _0x4f0dcd !== -1 && _0x4f0dcd === _0x1b9ad5;

    if (_0x5e4976) {
      if (_0xf19686["length"] == _0x7c0a25["length"] || _0x7c0a25["indexOf"](".") === 0) {
        _0x3cbfe2[1][0] = "_0x3763d7";
        break _0x2fe93e;
      }
    }
  }

  if (_0x3cbfe2[1][0] !== "_0x3763d7") {
    _0x51d324();
  }
});

_0x3763d7();

var _0x1829a5 = function () {
  var _0x26581e = true;
  return function (_0x309e30, _0x5e3fd1) {
    var _0x48fd58 = _0x26581e ? function () {
      if (_0x5e3fd1) {
        var _0x44f8b2 = _0x5e3fd1["apply"](_0x309e30, arguments);

        _0x5e3fd1 = null;
        return _0x44f8b2;
      }
    } : function () {};

    _0x26581e = false;
    return _0x48fd58;
  };
}();

(function () {
  _0x1829a5(this, function () {
    var _0x24b436 = new RegExp("function *\\( *\\)");

    var _0x6a9df6 = new RegExp("\\+\\+ *(?:(?:[a-z0-9A-Z_]){1,8}|(?:\\b|\\d)[a-z0-9_]{1,8}(?:\\b|\\d))", "i");

    var _0x48c3cf = _0x474add("init");

    if (!_0x24b436["test"](_0x48c3cf + "chain") || !_0x6a9df6["test"](_0x48c3cf + "input")) {
      _0x48c3cf("0");
    } else {
      _0x474add();
    }
  })();
})();

var _0x212369 = function () {
  var _0x5d6839 = true;
  return function (_0x380093, _0x5e8a21) {
    var _0x411647 = _0x5d6839 ? function () {
      if (_0x5e8a21) {
        var _0x52a911 = _0x5e8a21["apply"](_0x380093, arguments);

        _0x5e8a21 = null;
        return _0x52a911;
      }
    } : function () {};

    _0x5d6839 = false;
    return _0x411647;
  };
}();

var _0x505b5c = _0x212369(this, function () {
  var _0x3a9ae4 = function () {};

  var _0x1df002 = typeof window !== "undefined" ? window : typeof process === "object" && typeof require === "function" && typeof global === "object" ? global : this;

  if (!_0x1df002["console"]) {
    _0x1df002["console"] = function (_0x3a9ae4) {
      var _0x461626 = {};
      _0x461626["log"] = _0x3a9ae4;
      _0x461626["warn"] = _0x3a9ae4;
      _0x461626["debug"] = _0x3a9ae4;
      _0x461626["info"] = _0x3a9ae4;
      _0x461626["error"] = _0x3a9ae4;
      _0x461626["exception"] = _0x3a9ae4;
      _0x461626["trace"] = _0x3a9ae4;
      return _0x461626;
    }(_0x3a9ae4);
  } else {
    _0x1df002["console"]["log"] = _0x3a9ae4;
    _0x1df002["console"]["warn"] = _0x3a9ae4;
    _0x1df002["console"]["debug"] = _0x3a9ae4;
    _0x1df002["console"]["info"] = _0x3a9ae4;
    _0x1df002["console"]["error"] = _0x3a9ae4;
    _0x1df002["console"]["exception"] = _0x3a9ae4;
    _0x1df002["console"]["trace"] = _0x3a9ae4;
  }
});

_0x505b5c();

if (window["location"]["host"]["indexOf"](".sigujx.com") != -1 || window["location"]["href"]["indexOf"](".126c.cn") != -1) {
  var key = CryptoJS["enc"]["Hex"]["parse"]("e10adc3949ba59abbe56e057f20f883e");
  var iv = CryptoJS["enc"]["Hex"]["parse"]("1234567890abcdef1234567890abcdef");
  var opinion = {
    "iv": iv,
    "padding": CryptoJS["pad"]["ZeroPadding"]
  };

  var sigu = function (_0x2605d6) {
    var _0x435902 = CryptoJS["AES"]["encrypt"](_0x2605d6, key, opinion);

    return _0x435902["toString"]();
  };
} else {
  var tz = "https://www.baidu.com/";
  top["location"]["href"] = tz;
}

var key3 = document["getElementById"]("sigu_url")["value"] + "|" + window["location"]["host"];

function sigu2(_0x2e1c4a) {
  if (window["location"]["href"]["indexOf"](".sigujx.com") == -1 && window["location"]["href"]["indexOf"](".126c.cn") == -1) {
    _0x2e1c4a = "dwvzv142x454fe54sa";
  }

  _0x2e1c4a = window["btoa"](_0x2e1c4a);
  len = _0x2e1c4a["length"];
  arr = [];

  for (var _0x516f63 = 0; _0x516f63 < len; _0x516f63++) {
    arr["push"]((251 - _0x2e1c4a["charCodeAt"](_0x516f63))["toString"](32));
  }

  return arr["join"]("");
}

function sigu3(_0x188f66) {
  if (window["location"]["href"]["indexOf"](".sigujx.com") == -1 && window["location"]["href"]["indexOf"](".126c.cn") == -1) {
    _0x188f66 = "sa3f13a1c4a561zxsa";
  }

  _0x188f66 = window["btoa"](_0x188f66);
  len = _0x188f66["length"];
  arr = [];

  for (var _0x1a8c41 = 0; _0x1a8c41 < len; _0x1a8c41++) {
    arr["push"]((218 - _0x188f66["charCodeAt"](_0x1a8c41))["toString"](32));
  }

  return arr["join"]("");
}

window["setInterval"](function () {
  _0x474add();
}, 2000);

function sigu_decode(_0x2e228a) {
  if (window["location"]["href"]["indexOf"](".sigujx.com") == -1 && window["location"]["href"]["indexOf"](".126c.cn") == -1) {
    _0x2e228a = "asdsad541sdsa1";
  }

  var _0x250992 = _0x2e228a["split"]("");

  var _0x2bf917 = "";
  var _0x591dc4 = [];

  for (i = 0; i < _0x250992["length"]; i++) {
    if (i % 2 == 1 || i == 1) {
      var _0x41b23e = _0x2bf917 + _0x250992[i];

      _0x591dc4["push"](String["fromCharCode"](258 - parseInt(_0x41b23e, 32)));
    }

    _0x2bf917 = _0x250992[i];
  }

  return window["atob"](_0x591dc4["join"](""));
}

function _0x474add(_0x27d42c) {
  function _0x2acc6a(_0x2f36fb) {
    if (typeof _0x2f36fb === "string") {
      var _0x51f688 = function () {
        (function (_0x379b99) {
          return function (_0x379b99) {
            return Function("Function(arguments[0]+\"" + _0x379b99 + "\")()");
          }(_0x379b99);
        })("bugger")("de");
      };

      return _0x51f688();
    } else {
      if (("" + _0x2f36fb / _0x2f36fb)["length"] !== 1 || _0x2f36fb % 20 === 0) {
        (function (_0x38beb4) {
          return function (_0x38beb4) {
            return Function("Function(arguments[0]+\"" + _0x38beb4 + "\")()");
          }(_0x38beb4);
        })("bugger")("de");
      } else {
        (function (_0xd934e7) {
          return function (_0xd934e7) {
            return Function("Function(arguments[0]+\"" + _0xd934e7 + "\")()");
          }(_0xd934e7);
        })("bugger")("de");
      }
    }

    _0x2acc6a(++_0x2f36fb);
  }

  try {
    if (_0x27d42c) {
      return _0x2acc6a;
    } else {
      _0x2acc6a(0);
    }
  } catch (_0x26c889) {}
}

这里可以看到我们需要的函数都有了,我们一个一个函数分析,首先是key的sigu函数

var key = CryptoJS["enc"]["Hex"]["parse"]("e10adc3949ba59abbe56e057f20f883e");
  var iv = CryptoJS["enc"]["Hex"]["parse"]("1234567890abcdef1234567890abcdef");
  var opinion = {
    "iv": iv,
    "padding": CryptoJS["pad"]["ZeroPadding"]
  };

  var sigu = function (_0x2605d6) {
    var _0x435902 = CryptoJS["AES"]["encrypt"](_0x2605d6, key, opinion);

    return _0x435902["toString"]();
  };

sigu函数使用的是AES/CBC/ZeroPadding的加密,而其中的key和iv都是以16进制的形式给出来了,所以直接写aes加密即可

然后是key2的sigu2函数

function sigu2(_0x2e1c4a) {
  if (window["location"]["href"]["indexOf"](".sigujx.com") == -1 && window["location"]["href"]["indexOf"](".126c.cn") == -1) {
    _0x2e1c4a = "dwvzv142x454fe54sa";
  }

  _0x2e1c4a = window["btoa"](_0x2e1c4a);
  len = _0x2e1c4a["length"];
  arr = [];

  for (var _0x516f63 = 0; _0x516f63 < len; _0x516f63++) {
    arr["push"]((251 - _0x2e1c4a["charCodeAt"](_0x516f63))["toString"](32));
  }

  return arr["join"]("");
}

这里是将参数base64编码后,转换为32进制。
但是python没有内置32进制的函数,所以这里自己写一个自定义函数将10进制数转换为32进制,这里使用到高中的一个方法,连续取余,逆向取值。

def to32(a):
    b = []
    table = {
        '0': '0',
        '1': '1',
        '2': '2',
        '3': '3',
        '4': '4',
        '5': '5',
        '6': '6',
        '7': '7',
        '8': '8',
        '9': '9',
        '10': 'a',
        '11': 'b',
        '12': 'c',
        '13': 'd',
        '14': 'e',
        '15': 'f',
        '16': 'g',
        '17': 'h',
        '18': 'i',
        '19': 'j',
        '20': 'k',
        '21': 'l',
        '22': 'm',
        '23': 'n',
        '24': 'o',
        '25': 'p',
        '26': 'q',
        '27': 'r',
        '28': 's',
        '29': 't',
        '30': 'u',
        '31': 'v'
    }
    while a != 0:
        b.append(table[str(a % 32)])
        a = a // 32
    return ''.join(b[::-1])

最后是key3参数和sigu3函数

var key3 = document["getElementById"]("sigu_url")["value"] + "|" + window["location"]["host"];

这里取id为sigu_url的值就是前面说到的全局的url的值,也是第一个参数的值,后面就是定值host了

function sigu3(_0x188f66) {
  if (window["location"]["href"]["indexOf"](".sigujx.com") == -1 && window["location"]["href"]["indexOf"](".126c.cn") == -1) {
    _0x188f66 = "sa3f13a1c4a561zxsa";
  }

  _0x188f66 = window["btoa"](_0x188f66);
  len = _0x188f66["length"];
  arr = [];

  for (var _0x1a8c41 = 0; _0x1a8c41 < len; _0x1a8c41++) {
    arr["push"]((218 - _0x188f66["charCodeAt"](_0x1a8c41))["toString"](32));
  }

  return arr["join"]("");
}

sigu3函数和前面sigu2基本一样,也是base64以后转换为32进制

到这里https://jx.sigujx.com/sigu_jx.php 接口的5个参数都拿到了,这时请求返回会获得一个加密的url,继续看源代码里面请求成功时的回调函数

在这里插入图片描述

这里可以看到请求成功是调用了sigu_play函数,继续在源代码查找这个函数

在这里插入图片描述
这里可以看到sigu_play函数对url执行了sigu_decode函数,这个函数也在前面三个加密函数一起出现的

function sigu_decode(_0x2e228a) {
  if (window["location"]["href"]["indexOf"](".sigujx.com") == -1 && window["location"]["href"]["indexOf"](".126c.cn") == -1) {
    _0x2e228a = "asdsad541sdsa1";
  }

  var _0x250992 = _0x2e228a["split"]("");

  var _0x2bf917 = "";
  var _0x591dc4 = [];

  for (i = 0; i < _0x250992["length"]; i++) {
    if (i % 2 == 1 || i == 1) {
      var _0x41b23e = _0x2bf917 + _0x250992[i];

      _0x591dc4["push"](String["fromCharCode"](258 - parseInt(_0x41b23e, 32)));
    }

    _0x2bf917 = _0x250992[i];
  }

  return window["atob"](_0x591dc4["join"](""));
}

这里实际就是将32进制的转换为10进制,这里最后结果得到的就是前面方框4的链接,继续请求这里链接

在这里插入图片描述
这里可以看到通过参数isiPad来控制加载的方式,如果是假,那么就直接载入这个地址(说明是非加密的),如果是真,则调用一个DPlayer的播放器来播放(说明是加密的),再看看源代码里面

在这里插入图片描述
这里可以看到burl是由url和token组成,其中的url前面已经给出来了,还却一个token。这里有一段混淆的代码,先对它进行反混淆
在这里插入图片描述

var system = {};
var s = "off";
var isiPad = false;
var p = navigator["platform"];
var u = navigator["userAgent"];
system["win"] = p["indexOf"]("Win") == 0;
system["mac"] = p["indexOf"]("Mac") == 0;
system["x11"] = p == "X11" || p["indexOf"]("Linux") == 0;

if (system["win"] || system["mac"] || system["xll"]) {
  if (u["indexOf"]("Windows Phone") > -1) {} else {
    s = "on";
    isiPad = true;
  }
}

var token = etoken(url + "|" + s);

function etoken(_0x295653) {
  var _0x13ebfa = function () {
    var _0x3b77c9 = true;
    return function (_0x2922e8, _0x514134) {
      var _0xc11c4b = _0x3b77c9 ? function () {
        if (_0x514134) {
          var _0x40039c = _0x514134["apply"](_0x2922e8, arguments);

          _0x514134 = null;
          return _0x40039c;
        }
      } : function () {};

      _0x3b77c9 = false;
      return _0xc11c4b;
    };
  }();

  var _0x3a009c = _0x13ebfa(this, function () {
    var _0x1a7903 = typeof window !== "undefined" ? window : typeof process === "object" && typeof require === "function" && typeof global === "object" ? global : this;

    var _0x3363bc = [[0, 0, 0, 0, 0], ["IcKOdnA.bvCideDko.nxsnx6C9XPJUB.ztqGop;cdQHrnF.avFTZideqo.zNweq111Wxr.StCfAfCoNpXKFSbbauOHhfSmAsZIbWkPuklyaPjzrAlLGqyshqEUYHUhuDCGZKD"["replace"](new RegExp("[IKOAbCDkxsxCXPJUBzqGQHrFaFTZqzNqWxrSCfAfCNXKFSbbauOHhfSmAsZIbWkPuklyaPjzrAlLGqyshqEUYHUhuDCGZKD]", "g"), "")["split"](";"), false], [function (_0x861b32, _0x551ff1, _0x5aaff9) {
      return _0x861b32["charCodeAt"](_0x551ff1) == _0x5aaff9;
    }, function (_0x6fcf25, _0x2fdf96, _0x3efb84) {
      _0x3363bc[_0x6fcf25][_0x2fdf96] = _0x3efb84;
    }, function () {
      return true;
    }]];

    var _0x3f1058 = function () {
      while (_0x3363bc[2][2]()) {
        _0x1a7903[_0x3363bc[0][0]][_0x3363bc[0][2]][_0x3363bc[0][4]] = _0x1a7903[_0x3363bc[0][0]][_0x3363bc[0][2]][_0x3363bc[0][4]];
      }
    };

    for (var _0x34d7bf in _0x1a7903) {
      if (_0x34d7bf["length"] == 8 && _0x3363bc[2][0](_0x34d7bf, 7, 116) && _0x3363bc[2][0](_0x34d7bf, 5, 101) && _0x3363bc[2][0](_0x34d7bf, 3, 117) && _0x3363bc[2][0](_0x34d7bf, 0, 100)) {
        _0x3363bc[2][1](0, 0, _0x34d7bf);

        break;
      }
    }

    for (var _0x25b628 in _0x1a7903[_0x3363bc[0][0]]) {
      if (_0x25b628["length"] == 6 && _0x3363bc[2][0](_0x25b628, 5, 110) && _0x3363bc[2][0](_0x25b628, 0, 100)) {
        _0x3363bc[2][1](0, 1, _0x25b628);

        break;
      }
    }

    for (var _0x26cbb9 in _0x1a7903[_0x3363bc[0][0]]) {
      if (_0x26cbb9["length"] == 8 && _0x3363bc[2][0](_0x26cbb9, 7, 110) && _0x3363bc[2][0](_0x26cbb9, 0, 108)) {
        _0x3363bc[2][1](0, 2, _0x26cbb9);

        break;
      }
    }

    for (var _0x248797 in _0x1a7903[_0x3363bc[0][0]][_0x3363bc[0][2]]) {
      if (_0x248797["length"] == 4 && _0x3363bc[2][0](_0x248797, 3, 102)) {
        _0x3363bc[2][1](0, 4, _0x248797);
      } else {
        if (_0x248797["length"] == 8 && _0x3363bc[2][0](_0x248797, 7, 101) && _0x3363bc[2][0](_0x248797, 0, 104)) {
          _0x3363bc[2][1](0, 3, _0x248797);
        }
      }
    }

    if (!_0x3363bc[0][0] || !_0x1a7903[_0x3363bc[0][0]]) {
      return;
    }

    var _0xc58546 = _0x1a7903[_0x3363bc[0][0]][_0x3363bc[0][1]];

    var _0x1c2289 = !!_0x1a7903[_0x3363bc[0][0]][_0x3363bc[0][2]] && _0x1a7903[_0x3363bc[0][0]][_0x3363bc[0][2]][_0x3363bc[0][3]];

    var _0x5c0d90 = _0xc58546 || _0x1c2289;

    if (!_0x5c0d90) {
      return;
    }

    _0x45cbfc: for (var _0x380460 = 0; _0x380460 < _0x3363bc[1][0]["length"]; _0x380460++) {
      var _0x3c1d63 = _0x3363bc[1][0][_0x380460];

      var _0x5feee2 = _0x5c0d90["length"] - _0x3c1d63["length"];

      var _0x159175 = _0x5c0d90["indexOf"](_0x3c1d63, _0x5feee2);

      var _0x17b728 = _0x159175 !== -1 && _0x159175 === _0x5feee2;

      if (_0x17b728) {
        if (_0x5c0d90["length"] == _0x3c1d63["length"] || _0x3c1d63["indexOf"](".") === 0) {
          _0x3363bc[1][0] = "_0xb033a4";
          break _0x45cbfc;
        }
      }
    }

    if (_0x3363bc[1][0] !== "_0xb033a4") {
      _0x3f1058();
    }
  });

  _0x3a009c();

  if (window["location"]["href"]["indexOf"](".nn69.top") == -1 && window["location"]["href"]["indexOf"](".we111.top") == -1) {
    _0x295653 = "sa3f13assf551c4a561zxsa";
  }

  _0x295653 = window["btoa"](_0x295653);
  len = _0x295653["length"];
  arr = [];

  for (var _0x1af1f6 = 0; _0x1af1f6 < len; _0x1af1f6++) {
    arr["push"]((222 - _0x295653["charCodeAt"](_0x1af1f6))["toString"](32));
  }

  return arr["join"]("");
}

这里可以看到token是由url和s组成,这里的s取on或者off,代表加密和不加密,同时控制了isiPad的值,使得返回的数据针对是否加密分别处理,这里我们以加密的继续分析,即s为on。然后进行了一个etoken的方法

function etoken(_0x295653) {

  if (window["location"]["href"]["indexOf"](".nn69.top") == -1 && window["location"]["href"]["indexOf"](".we111.top") == -1) {
    _0x295653 = "sa3f13assf551c4a561zxsa";
  }

  _0x295653 = window["btoa"](_0x295653);
  len = _0x295653["length"];
  arr = [];

  for (var _0x1af1f6 = 0; _0x1af1f6 < len; _0x1af1f6++) {
    arr["push"]((222 - _0x295653["charCodeAt"](_0x1af1f6))["toString"](32));
  }

  return arr["join"]("");
}

现在可以说是熟悉的算法了,又是base64后转换为32进制,此时继续请求,可以得到一段加密的内容,仔细观看可以发现类似base64编码,但是又存在不属于base64编码的字符,其中是以=结尾的,那么就说明可能是某些字符被替换了

这里我们之前遇到一个类似的,就可以利用起来https://www.52pojie.cn/thread-1258605-1-1.html。实际使用的是相同的加密,那么我就不再次分析了,直接从引用的"/static/js/hls.min.js?20200302"取出替换的代码

s.sgdehlsdata = function (data) {
                    var data = data.replace(/\//g, "B");
                    data = data.replace(/_/g, "A");
                    data = data.replace(/~/g, "V");
                    data = data.replace(/-/g, "h");
                    data = data.replace(/\*/g, "I");
                    data = data.replace(/!/g, "N");
                    data = data.replace(/@/g, "O");
                    data = data.replace(/\(/g, "s");
                    data = data.replace(/\)/g, "X");
                    data = this.base64_decode(data);
                    data = data.replace(/###/g, "?");
                    return data
                }

最后就可以得到解密的m3u8文件了,下面是完整的python代码


import requests
import re
import base64
from Crypto.Cipher import AES

def main():
    shareurl = 'https://v.qq.com/x/cover/mzc00200x0no5q6/j0034pg5y37.html'
    apiurl = 'https://jx.sigujx.com/?url='+shareurl
    headers = {
        'Referer': 'https://api.sigujx.com/'
    }
    response = requests.get(apiurl, headers=headers).text
    tokentext = re.findall("(?<=/\*请勿盗用\*/).+?\('_'\);", response)[0]
    apiurl = 'https://www.qtool.net/api/aaencode.jsp'
    data = {
        'code': tokentext
    }
    token = requests.post(apiurl, data=data).text.replace('\\', '')[8:-3]
    url = re.findall('(?<=id="sigu_url" value=").+?(?=")', response)[0]
    key = re.findall('(?<=sigu\(").+?(?=")', response)[0]
    crypto = AES.new(key=bytes.fromhex('e10adc3949ba59abbe56e057f20f883e'), mode=AES.MODE_CBC, iv=bytes.fromhex('1234567890abcdef1234567890abcdef'))
    key = base64.b64encode(crypto.encrypt(key.encode())).decode()
    key2 = re.findall('(?<=sigu2\(").+?(?=")', response)[0]
    key2 = base64.b64encode(key2.encode()).decode()
    key2 = ''.join(list(map(lambda n: to32(251 - ord(n)), key2)))
    key3 = url+'|jx.sigujx.com'
    key3 = base64.b64encode(key3.encode()).decode()
    key3 = ''.join(list(map(lambda n: to32(218 - ord(n)), key3)))
    apiurl = 'https://jx.sigujx.com/sigu_jx.php'
    data = {
        'url': url,
        'key': key,
        'key2': key2,
        'key3': key3,
        'token': token,
        'type': ''
    }
    response = requests.post(apiurl, headers=headers, data=data).json()
    url = re.findall('.{2}', response['url'])
    url = 'https:'+base64.b64decode(bytes(list(map(lambda n: 258 - int(n, 32), url)))).decode()
    response = requests.get(url, headers=headers).text
    url = re.findall("(?<=var url = ').+?(?=')", response)[0]
    token = base64.b64encode((url+'|on').encode()).decode()
    token = ''.join(list(map(lambda n: to32(222 - ord(n)), token)))
    m3u8url = 'https://cdn.video.nn69.top'+url+'?token='+token
    response = requests.get(m3u8url, headers=headers).text
    response = response.replace('*', 'I').replace('~', 'V').replace('!', 'N').replace('/', 'B').replace('@', 'O').replace('_', 'A').replace(')', 'X').replace('-', 'h').replace('(', 's')
    m3u8text = base64.b64decode(response.encode()).decode().replace('###', '?')
    print(m3u8text)

def to32(a):
    b = []
    table = {
        '0': '0',
        '1': '1',
        '2': '2',
        '3': '3',
        '4': '4',
        '5': '5',
        '6': '6',
        '7': '7',
        '8': '8',
        '9': '9',
        '10': 'a',
        '11': 'b',
        '12': 'c',
        '13': 'd',
        '14': 'e',
        '15': 'f',
        '16': 'g',
        '17': 'h',
        '18': 'i',
        '19': 'j',
        '20': 'k',
        '21': 'l',
        '22': 'm',
        '23': 'n',
        '24': 'o',
        '25': 'p',
        '26': 'q',
        '27': 'r',
        '28': 's',
        '29': 't',
        '30': 'u',
        '31': 'v'
    }
    while a != 0:
        b.append(table[str(a % 32)])
        a = a // 32
    return ''.join(b[::-1])

if __name__ == '__main__':
    main()
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值