按照惯例,刷新网站,搜索m3u8,发现含有m3u8的包,但是内容进行了加密。
在下方搜索框搜索[xiaoe],确定js文件的位置。在r处打上断点,发现函数N接收密文,和参数,返回真正的数据,复制函数在js文件中。
缺啥补啥,在网页中取复制js代码,在控制台得到t和e的值作为函数N的输入参数
怎么找M函数,鼠标放在M上尽可以出现来源了。
发现缺少M函数,复制M函数
发现O函数没有定义
在M函数内部找到O函数并打上断点
在控制台输出
猜测为MD5加密,在在线MD5加密网站进行加密,发现结果一致,因此导入加密包
const CryptoJS = require('crypto')
function O(data){
const hash = CryptoJS.createHash('md5');
hash.update(data);
return hash.digest('hex');
}
引入包后,在运行发现缺少P
定位到P的位置,它在M函数内部,但其实P一开始就定义在乐M的上面,这是一个webpack格式,r函数调用ffdf键。打上断点,直接刷新,不要断点跳转。可以跳到r的位置。
从var e一直复制到r,p
复制完之后进行自执行函数改写。
!function("行参"){"加载器"}(['模块'])
/*自执行函数,模块如果为数组形式则下标执行,如果为字典格式,则用key进行执行。
逆向时遇到webpack,要复制其中的加载器和模块,自己写自执行函数。*/
/*网页中的webpack形式,进行改写*/
var zy;
!function xx(t) {
var e = {};
function r(i) {
if (e[i])
return e[i].exports;
var n = e[i] = {
i: i,
l: !1,
exports: {}
};
return t[i].call(n.exports, n, n.exports, r),
n.l = !0,
n.exports
}return r.m = t,
r.c = e,
r.d = function(t, e, i) {
r.o(t, e) || Object.defineProperty(t, e, {
enumerable: !0,
get: i
})
}
,
r.r = function(t) {
"undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, {
value: "Module"
}),
Object.defineProperty(t, "__esModule", {
value: !0
})
}
,
r.t = function(t, e) {
if (1 & e && (t = r(t)),
8 & e)
return t;
if (4 & e && "object" == typeof t && t && t.__esModule)
return t;
var i = Object.create(null);
if (r.r(i),
Object.defineProperty(i, "default", {
enumerable: !0,
value: t
}),
2 & e && "string" != typeof t)
for (var n in t)
r.d(i, n, function(e) {
return t[e]
}
.bind(null, n));
return i
}
,
r.n = function(t) {
var e = t && t.__esModule ? function() {
return t.default
}
: function() {
return t
}
;
return r.d(e, "a", e),
e
}
,
r.o = function(t, e) {
return Object.prototype.hasOwnProperty.call(t, e)
}
,
r.p = "",
zy=r
}({
"ffdf": function(t, r, i) {
"use strict";
i.r(r),
i.d(r, "version", (function() {
return n
}
)),
i.d(r, "VERSION", (function() {
return s
}
)),
i.d(r, "atob", (function() {
return I
}
)),
i.d(r, "atobPolyfill", (function() {
return x
}
)),
i.d(r, "btoa", (function() {
return v
}
)),
i.d(r, "btoaPolyfill", (function() {
return m
}
)),
i.d(r, "fromBase64", (function() {
return M
}
)),
i.d(r, "toBase64", (function() {
return _
}
)),
i.d(r, "utob", (function() {
return S
}
)),
i.d(r, "encode", (function() {
return _
}
)),
i.d(r, "encodeURI", (function() {
return A
}
)),
i.d(r, "encodeURL", (function() {
return A
}
)),
i.d(r, "btou", (function() {
return k
}
)),
i.d(r, "decode", (function() {
return M
}
)),
i.d(r, "isValid", (function() {
return F
}
)),
i.d(r, "fromUint8Array", (function() {
return b
}
)),
i.d(r, "toUint8Array", (function() {
return D
}
)),
i.d(r, "extendString", (function() {
return U
}
)),
i.d(r, "extendUint8Array", (function() {
return B
}
)),
i.d(r, "extendBuiltins", (function() {
return G
}
)),
i.d(r, "Base64", (function() {
return j
}
));
const n = "3.7.7"
, s = n
, a = "function" == typeof e
, o = "function" == typeof TextDecoder ? new TextDecoder : void 0
, l = "function" == typeof TextEncoder ? new TextEncoder : void 0
, c = Array.prototype.slice.call("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=")
, u = (t=>{
let e = {};
return t.forEach((t,r)=>e[t] = r),
e
}
)(c)
, h = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/
, d = String.fromCharCode.bind(String)
, f = "function" == typeof Uint8Array.from ? Uint8Array.from.bind(Uint8Array) : t=>new Uint8Array(Array.prototype.slice.call(t, 0))
, p = t=>t.replace(/=/g, "").replace(/[+\/]/g, t=>"+" == t ? "-" : "_")
, g = t=>t.replace(/[^A-Za-z0-9\+\/]/g, "")
, m = t=>{
let e, r, i, n, s = "";
const a = t.length % 3;
for (let o = 0; o < t.length; ) {
if ((r = t.charCodeAt(o++)) > 255 || (i = t.charCodeAt(o++)) > 255 || (n = t.charCodeAt(o++)) > 255)
throw new TypeError("invalid character found");
e = r << 16 | i << 8 | n,
s += c[e >> 18 & 63] + c[e >> 12 & 63] + c[e >> 6 & 63] + c[63 & e]
}
return a ? s.slice(0, a - 3) + "===".substring(a) : s
}
, v = "function" == typeof btoa ? t=>btoa(t) : a ? t=>e.from(t, "binary").toString("base64") : m
, y = a ? t=>e.from(t).toString("base64") : t=>{
let e = [];
for (let r = 0, i = t.length; r < i; r += 4096)
e.push(d.apply(null, t.subarray(r, r + 4096)));
return v(e.join(""))
}
, b = (t,e=!1)=>e ? p(y(t)) : y(t)
, T = t=>{
if (t.length < 2)
return (e = t.charCodeAt(0)) < 128 ? t : e < 2048 ? d(192 | e >>> 6) + d(128 | 63 & e) : d(224 | e >>> 12 & 15) + d(128 | e >>> 6 & 63) + d(128 | 63 & e);
var e = 65536 + 1024 * (t.charCodeAt(0) - 55296) + (t.charCodeAt(1) - 56320);
return d(240 | e >>> 18 & 7) + d(128 | e >>> 12 & 63) + d(128 | e >>> 6 & 63) + d(128 | 63 & e)
}
, E = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g
, S = t=>t.replace(E, T)
, w = a ? t=>e.from(t, "utf8").toString("base64") : l ? t=>y(l.encode(t)) : t=>v(S(t))
, _ = (t,e=!1)=>e ? p(w(t)) : w(t)
, A = t=>_(t, !0)
, R = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g
, L = t=>{
switch (t.length) {
case 4:
var e = ((7 & t.charCodeAt(0)) << 18 | (63 & t.charCodeAt(1)) << 12 | (63 & t.charCodeAt(2)) << 6 | 63 & t.charCodeAt(3)) - 65536;
return d(55296 + (e >>> 10)) + d(56320 + (1023 & e));
case 3:
return d((15 & t.charCodeAt(0)) << 12 | (63 & t.charCodeAt(1)) << 6 | 63 & t.charCodeAt(2));
default:
return d((31 & t.charCodeAt(0)) << 6 | 63 & t.charCodeAt(1))
}
}
, k = t=>t.replace(R, L)
, x = t=>{
if (t = t.replace(/\s+/g, ""),
!h.test(t))
throw new TypeError("malformed base64.");
t += "==".slice(2 - (3 & t.length));
let e, r, i, n = "";
for (let s = 0; s < t.length; )
e = u[t.charAt(s++)] << 18 | u[t.charAt(s++)] << 12 | (r = u[t.charAt(s++)]) << 6 | (i = u[t.charAt(s++)]),
n += 64 === r ? d(e >> 16 & 255) : 64 === i ? d(e >> 16 & 255, e >> 8 & 255) : d(e >> 16 & 255, e >> 8 & 255, 255 & e);
return n
}
, I = "function" == typeof atob ? t=>atob(g(t)) : a ? t=>e.from(t, "base64").toString("binary") : x
, C = a ? t=>f(e.from(t, "base64")) : t=>f(I(t).split("").map(t=>t.charCodeAt(0)))
, D = t=>C(O(t))
, P = a ? t=>e.from(t, "base64").toString("utf8") : o ? t=>o.decode(C(t)) : t=>k(I(t))
, O = t=>g(t.replace(/[-_]/g, t=>"-" == t ? "+" : "/"))
, M = t=>P(O(t))
, F = t=>{
if ("string" != typeof t)
return !1;
const e = t.replace(/\s+/g, "").replace(/={0,2}$/, "");
return !/[^\s0-9a-zA-Z\+/]/.test(e) || !/[^\s0-9a-zA-Z\-_]/.test(e)
}
, N = t=>({
value: t,
enumerable: !1,
writable: !0,
configurable: !0
})
, U = function() {
const t = (t,e)=>Object.defineProperty(String.prototype, t, N(e));
t("fromBase64", (function() {
return M(this)
}
)),
t("toBase64", (function(t) {
return _(this, t)
}
)),
t("toBase64URI", (function() {
return _(this, !0)
}
)),
t("toBase64URL", (function() {
return _(this, !0)
}
)),
t("toUint8Array", (function() {
return D(this)
}
))
}
, B = function() {
const t = (t,e)=>Object.defineProperty(Uint8Array.prototype, t, N(e));
t("toBase64", (function(t) {
return b(this, t)
}
)),
t("toBase64URI", (function() {
return b(this, !0)
}
)),
t("toBase64URL", (function() {
return b(this, !0)
}
))
}
, G = ()=>{
U(),
B()
}
, j = {
version: n,
VERSION: s,
atob: I,
atobPolyfill: x,
btoa: v,
btoaPolyfill: m,
fromBase64: M,
toBase64: _,
encode: _,
encodeURI: A,
encodeURL: A,
utob: S,
btou: k,
decode: M,
isValid: F,
fromUint8Array: b,
toUint8Array: D,
extendString: U,
extendUint8Array: B,
extendBuiltins: G
}
}
})
P = zy("ffdf")
在加载器的最后,令一个变量zy=r,接收 上面定义的r函数,然后接收模块中的key值,复制给新的变量P。
全代码展示:
const CryptoJS = require('crypto')
function O(data){
const hash = CryptoJS.createHash('md5');
hash.update(data);
return hash.digest('hex');
}
var zy;
!function xx(t) {
var e = {};
function r(i) {
if (e[i])
return e[i].exports;
var n = e[i] = {
i: i,
l: !1,
exports: {}
};
return t[i].call(n.exports, n, n.exports, r),
n.l = !0,
n.exports
}return r.m = t,
r.c = e,
r.d = function(t, e, i) {
r.o(t, e) || Object.defineProperty(t, e, {
enumerable: !0,
get: i
})
}
,
r.r = function(t) {
"undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, {
value: "Module"
}),
Object.defineProperty(t, "__esModule", {
value: !0
})
}
,
r.t = function(t, e) {
if (1 & e && (t = r(t)),
8 & e)
return t;
if (4 & e && "object" == typeof t && t && t.__esModule)
return t;
var i = Object.create(null);
if (r.r(i),
Object.defineProperty(i, "default", {
enumerable: !0,
value: t
}),
2 & e && "string" != typeof t)
for (var n in t)
r.d(i, n, function(e) {
return t[e]
}
.bind(null, n));
return i
}
,
r.n = function(t) {
var e = t && t.__esModule ? function() {
return t.default
}
: function() {
return t
}
;
return r.d(e, "a", e),
e
}
,
r.o = function(t, e) {
return Object.prototype.hasOwnProperty.call(t, e)
}
,
r.p = "",
zy=r
}({
"ffdf": function(t, r, i) {
"use strict";
i.r(r),
i.d(r, "version", (function() {
return n
}
)),
i.d(r, "VERSION", (function() {
return s
}
)),
i.d(r, "atob", (function() {
return I
}
)),
i.d(r, "atobPolyfill", (function() {
return x
}
)),
i.d(r, "btoa", (function() {
return v
}
)),
i.d(r, "btoaPolyfill", (function() {
return m
}
)),
i.d(r, "fromBase64", (function() {
return M
}
)),
i.d(r, "toBase64", (function() {
return _
}
)),
i.d(r, "utob", (function() {
return S
}
)),
i.d(r, "encode", (function() {
return _
}
)),
i.d(r, "encodeURI", (function() {
return A
}
)),
i.d(r, "encodeURL", (function() {
return A
}
)),
i.d(r, "btou", (function() {
return k
}
)),
i.d(r, "decode", (function() {
return M
}
)),
i.d(r, "isValid", (function() {
return F
}
)),
i.d(r, "fromUint8Array", (function() {
return b
}
)),
i.d(r, "toUint8Array", (function() {
return D
}
)),
i.d(r, "extendString", (function() {
return U
}
)),
i.d(r, "extendUint8Array", (function() {
return B
}
)),
i.d(r, "extendBuiltins", (function() {
return G
}
)),
i.d(r, "Base64", (function() {
return j
}
));
const n = "3.7.7"
, s = n
, a = "function" == typeof e
, o = "function" == typeof TextDecoder ? new TextDecoder : void 0
, l = "function" == typeof TextEncoder ? new TextEncoder : void 0
, c = Array.prototype.slice.call("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=")
, u = (t=>{
let e = {};
return t.forEach((t,r)=>e[t] = r),
e
}
)(c)
, h = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/
, d = String.fromCharCode.bind(String)
, f = "function" == typeof Uint8Array.from ? Uint8Array.from.bind(Uint8Array) : t=>new Uint8Array(Array.prototype.slice.call(t, 0))
, p = t=>t.replace(/=/g, "").replace(/[+\/]/g, t=>"+" == t ? "-" : "_")
, g = t=>t.replace(/[^A-Za-z0-9\+\/]/g, "")
, m = t=>{
let e, r, i, n, s = "";
const a = t.length % 3;
for (let o = 0; o < t.length; ) {
if ((r = t.charCodeAt(o++)) > 255 || (i = t.charCodeAt(o++)) > 255 || (n = t.charCodeAt(o++)) > 255)
throw new TypeError("invalid character found");
e = r << 16 | i << 8 | n,
s += c[e >> 18 & 63] + c[e >> 12 & 63] + c[e >> 6 & 63] + c[63 & e]
}
return a ? s.slice(0, a - 3) + "===".substring(a) : s
}
, v = "function" == typeof btoa ? t=>btoa(t) : a ? t=>e.from(t, "binary").toString("base64") : m
, y = a ? t=>e.from(t).toString("base64") : t=>{
let e = [];
for (let r = 0, i = t.length; r < i; r += 4096)
e.push(d.apply(null, t.subarray(r, r + 4096)));
return v(e.join(""))
}
, b = (t,e=!1)=>e ? p(y(t)) : y(t)
, T = t=>{
if (t.length < 2)
return (e = t.charCodeAt(0)) < 128 ? t : e < 2048 ? d(192 | e >>> 6) + d(128 | 63 & e) : d(224 | e >>> 12 & 15) + d(128 | e >>> 6 & 63) + d(128 | 63 & e);
var e = 65536 + 1024 * (t.charCodeAt(0) - 55296) + (t.charCodeAt(1) - 56320);
return d(240 | e >>> 18 & 7) + d(128 | e >>> 12 & 63) + d(128 | e >>> 6 & 63) + d(128 | 63 & e)
}
, E = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g
, S = t=>t.replace(E, T)
, w = a ? t=>e.from(t, "utf8").toString("base64") : l ? t=>y(l.encode(t)) : t=>v(S(t))
, _ = (t,e=!1)=>e ? p(w(t)) : w(t)
, A = t=>_(t, !0)
, R = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g
, L = t=>{
switch (t.length) {
case 4:
var e = ((7 & t.charCodeAt(0)) << 18 | (63 & t.charCodeAt(1)) << 12 | (63 & t.charCodeAt(2)) << 6 | 63 & t.charCodeAt(3)) - 65536;
return d(55296 + (e >>> 10)) + d(56320 + (1023 & e));
case 3:
return d((15 & t.charCodeAt(0)) << 12 | (63 & t.charCodeAt(1)) << 6 | 63 & t.charCodeAt(2));
default:
return d((31 & t.charCodeAt(0)) << 6 | 63 & t.charCodeAt(1))
}
}
, k = t=>t.replace(R, L)
, x = t=>{
if (t = t.replace(/\s+/g, ""),
!h.test(t))
throw new TypeError("malformed base64.");
t += "==".slice(2 - (3 & t.length));
let e, r, i, n = "";
for (let s = 0; s < t.length; )
e = u[t.charAt(s++)] << 18 | u[t.charAt(s++)] << 12 | (r = u[t.charAt(s++)]) << 6 | (i = u[t.charAt(s++)]),
n += 64 === r ? d(e >> 16 & 255) : 64 === i ? d(e >> 16 & 255, e >> 8 & 255) : d(e >> 16 & 255, e >> 8 & 255, 255 & e);
return n
}
, I = "function" == typeof atob ? t=>atob(g(t)) : a ? t=>e.from(t, "base64").toString("binary") : x
, C = a ? t=>f(e.from(t, "base64")) : t=>f(I(t).split("").map(t=>t.charCodeAt(0)))
, D = t=>C(O(t))
, P = a ? t=>e.from(t, "base64").toString("utf8") : o ? t=>o.decode(C(t)) : t=>k(I(t))
, O = t=>g(t.replace(/[-_]/g, t=>"-" == t ? "+" : "/"))
, M = t=>P(O(t))
, F = t=>{
if ("string" != typeof t)
return !1;
const e = t.replace(/\s+/g, "").replace(/={0,2}$/, "");
return !/[^\s0-9a-zA-Z\+/]/.test(e) || !/[^\s0-9a-zA-Z\-_]/.test(e)
}
, N = t=>({
value: t,
enumerable: !1,
writable: !0,
configurable: !0
})
, U = function() {
const t = (t,e)=>Object.defineProperty(String.prototype, t, N(e));
t("fromBase64", (function() {
return M(this)
}
)),
t("toBase64", (function(t) {
return _(this, t)
}
)),
t("toBase64URI", (function() {
return _(this, !0)
}
)),
t("toBase64URL", (function() {
return _(this, !0)
}
)),
t("toUint8Array", (function() {
return D(this)
}
))
}
, B = function() {
const t = (t,e)=>Object.defineProperty(Uint8Array.prototype, t, N(e));
t("toBase64", (function(t) {
return b(this, t)
}
)),
t("toBase64URI", (function() {
return b(this, !0)
}
)),
t("toBase64URL", (function() {
return b(this, !0)
}
))
}
, G = ()=>{
U(),
B()
}
, j = {
version: n,
VERSION: s,
atob: I,
atobPolyfill: x,
btoa: v,
btoaPolyfill: m,
fromBase64: M,
toBase64: _,
encode: _,
encodeURI: A,
encodeURL: A,
utob: S,
btou: k,
decode: M,
isValid: F,
fromUint8Array: b,
toUint8Array: D,
extendString: U,
extendUint8Array: B,
extendBuiltins: G
}
}
})
P = zy("ffdf")
/* 上述代码使md5加密*/
M = {
encrypt: function (t) {
var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : "appbgzjnopv1917";
t = P.encode(t);
for (var r = Math.floor(t.length / 2), i = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", n = i.split("").reduce((function (t, e, r) {
return t[e] = r,
t
}
), {}), s = Math.floor(64 * Math.random()), a = i[s], o = O(e + a).substr(s % 8, s % 8 + 7).split("").map((function (t) {
return t.charCodeAt()
}
)), l = "", c = 0, u = 0; u < t.length; u++)
l += i[((c = c == o.length ? 0 : c) + n[t[u]] + o[c++]) % 65],
r && (l += t.slice(u + 1, u + 1 + r),
u += r);
return encodeURIComponent(a + l)
},
decode: function (t) {
var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : "appbgzjnopv1917";
e = O(e);
var r = 3
, i = +(t = decodeURIComponent(t)).substr(-r)[1]
, n = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
, s = n.split("").reduce((function (t, e, r) {
return t[e] = r,
t
}
), {})
, a = t[0]
, o = n.indexOf(a)
, l = O(e + a).substr(o % 8, o % 8 + 7).split("").map((function (t) {
return t.charCodeAt()
}
));
t = t.substr(1, t.length - r - 1);
for (var c = "", u = 0, h = 0, d = 0; d < t.length; d++) {
for (h = h == l.length ? 0 : h,
u = s[t[d]] - h - l[h++]; u < 0;)
u += 65;
c += n[u],
i && (c += t.slice(d + 1, d + 1 + i),
d += i)
}
return P.decode(c)
}
}
N = function (t, e) {
if ("string" == typeof t && t.startsWith("[xiaoe]")) {
var r = M && M.decode(t.substring("[xiaoe]".length, t.length), e)
, i = /#EXT-X-KEY:[^\n]*URI="(.*)"[^\n]*\n/i
, n = r.match(i);
return n && "" === n[1] && (r = r.replace(i, "")),
"string" == typeof r && r.indexOf("#EXTM3U"),
r
}
return t
}
t = '[xiaoe]K8q87%2BrwqBDeJ0%2BHQCBTj5W%2B%3DKbh5LrD44%3DsuELzP16Ev45L518ae%3DMbZ44J7HMMgKrTq9Qo2Hr3P%2BshH%2BGf92c3G%3DgIO8ld%2FHM%2B1KK%3Du8AIBHas3775F7WOxrc8UMvoOy4BsQc69JaaizsfPELH308ck%3DHLr19rpLgIH83%2B1MrAtCnKL4RYA%2FL0358FL4IHw2972DtbZ44J7HMMgKss44xAuG