分类: 建站进阶

  • m3u8的ts文件的PES加解密分析以及示例

    m3u8的ts文件的PES加解密分析以及示例

    一、前言

    最近有朋友问我,某个视频网站也是阿里ts加密方式。恰巧51假期,就拿来分析一番,一看代码与之前某视频网的加密方法几乎完全一样。唯一不同的是 AES解密时逻辑稍有不同。还有一些奇怪的问题,同时发现,自己写过的代码,自己都已经不理解了,之前吾爱发的解密文章,被xx了,综合种种吧,冒出了写此文,算是一个复习,同时把方法分享给大家。此外,前些日子有个朋友在帖子中提到了PES解密的问题,希望此文也可以帮助到他。@VOOV

    二、TS文件结构概述

    1、几个基本概念
    ES流(Elementary Stream) 基本码流,不分段的音频、视频或其他信息的连续码流。
    PES流 把基本流ES分割成段,并加上相应头文件打包成形的打包基本码流。PES是打包过的ES,已经插入PTS和DTS,一般一个PES是一帧图像。
    TS流(Transport Stream) 传输流,将具有共同时间基准或独立时间基准的一个或多个PES组合(复合)而成的单一数据流(用于数据传输)。
    其数据内容可包含视频、音频、字幕等数据。将一个视频切成多个ts文件,实现视频的分段传输。多用于电视媒体。

    2、ts文件格式
    ts文件由ts数据包组成,每个包大小为188字节(或204字节,在188个字节后加上16字节的CRC校验数据,其他格式一样),每个数据包存储的内容可能不同,可能是视频、音频、字幕,或索引表信息,索引表就类似于一本书的目录,通过目录,就可以找到需要的章节,章节就类似于视频或音频等数据。
    注:本文所描述的ts包,均为188字节。

    ts数据包 由 4字节包头、附加数据(一般用来填充,为了满足188字节)、负载数据(即PES的部分数据)如下图:

    一个完整的PES包数据,可能存在于多个ts数据包中,也就是说,一个ts包中,可能含有pes包的包头,也可能仅仅含有pes包的负载数据.
    下图展示了,PES包是如何转为TS包的。

    下面来分析占4字节(32比特)ts包头的结构以及附加域(长度不定)的结构。先上图。

    这里我们仅分析我们用到的字段,其中头中用到4个字段值,附加域只用到长度字段。如下表。

    序号标识位数说明
    0sync_byte8 bits同步字节,固定是0x47
    即每个ts包的首字节都是0x47
    2payload_unit_start_indicator1 bit负载单元开始标识
    用来判断是否是pes包的起始包
    若为0,则表示非起始包。
    非PES起始包,不含有PES包头
    4PID(Packet ID)13 bitsts包的数据类型
    ts包有几种数据类型:
    PAT、PMT、音频、视频、字幕等
    6adaptation_field_control2 bits附加域数据标识,有如下值:
    00:供未来使用,出ISO/IEC所保留
    01:无adaptation field,仅有效载荷
    10:仅有Adaptation field,无有效载荷
    11:Adaptation field后,带有效载荷
    翻译下:
    因为ts包长度固定188字节,因此
    若附加域数据过多,就会无法装载payload
    附加域中的字段
    0adaptation field length8 bits自适应域长度,后面数据长度
    除去本字段外,附加域其余字段的长度

    表中提及的PAT、PMT相当于一本书的目录,PAT相当于目录的目录,通过他们就可以找到某视频的位置。
    PAT的pid为0,首先我们就会分析PAT。
    接下来分析下PES头的数据格式。为我们后面解密做铺垫。先上图。

    字段很多,只分析我们需要的字段。如下表:

    序号标识位数说明
    0pes开始标识24 bitspes包开始标识
    固定值:0x000001
    10PES头中后面数据的长度8 bitspes头后面字段的长度
    pes头的长度就等于:
    本字段以及之前所有字段的长度
    加上本字段的值

    这里其实只要拿到pes头数据的长度。显然通过第10个字段,就可以计算出pes头的长度了。
    以上知识点,就可以支撑我们继续分析ts文件的加解密了。

    三、ts加密分析

    结合代码,我们分析下加密的逻辑。

    为了便于调试,这里我用未解密的video.ts文件作为样例,以及自己写的解密demo,来分析。
    (关于demo以及源代码等,我会放在文末)

    用其他软件(我用SublimeText)以16进制的形式,打开video.ts。
    这个一直开着,用来与代码读取的数据进行对比。看我们代码读的数据是什么。为什么这么读。

    a、首先找到ts文件数据解析函数。这里就是append(…)函数。(关于如何定位此函数,请参考我之前的文章)

    运行demo, 输入key,导入ts。提前在append函数首行打上断点。点击开始解密。会进入我们的断点。

    接下来看下我们传入的ts数据。

    以16进制的形式打印e1的值,与我们的video.ts数据对比,是一致的。
    看下图(此步骤,没啥意义,就是为了找找感觉)

    继续,在587行 C = syncOffset(e); 代码处添加断点,继续执行,程序会停留在此断点。
    此函数是在找 ts包的起始偏移,因为每个ts包都是188字节,
    所以此函数就通过判断连续3个188字节的首字节是否是71(16进制0x47), 若是则确定此索引为起始索引。
    我们这里都是0,也就是ts文件的第一个字节就是0x47,细心的朋友,已经发现了。

    接下来进入循环开始解析ts数据了。注意代码中 bill开头的函数与变量,是用来解密的。暂时忽略。
    在638行,也就是for循环的第一行,加断点,继续执行,会停在这里。我们分析下for循环的条件。先看看图。

    看637行的for循环

    for (o -= (o + C) % 188, a = C; a < o; a += 188)

    这里C是587行同步偏移返回的值,我们这里都是0。所以for循环就等于以下:

    for (o -= o % 188, a = 0; a < o; a += 188)

    这就清晰多了
    这里只有2个变量,a和o,a初始值是0,然后每次循环累加188,看看o是哪里来的。
    在本函数的第三行,也就是568行,看到 o = e.length, e在上一行,就是我们ts数据的uint8数组。
    因此,o就是ts数据的总长度, 那么o -= o % 188,是什么意思?
    先用总长度对188取余,然后总长度再减去余数, 也就是说,是为了保证我们循环总长度为188的整数倍。
    为什么这么做?是为了循环体内,不出现数组越界情况。(循环内部会分析)
    延伸下,这里循环结束后,取余出去的那部分数据不就没有分析到了嘛。
    所以当循环结束后,还得解析取余出去的那部分数据。这样整个ts文件数据就都被解析到了。

    继续,看638行的 if (71 === e[a]) ,显然这是在判断ts包的首字节是否为71(71是十进制,16进制0x47)
    如果首字节是0x47,则分析此包数据。否则直接报错。
    此时a为0,那么我们看看e[0]的值,确实是71。
    去之前打开的video.ts文件,看看第一个字节是不是0x47。一定是的。

    目前,我们是在video.ts文件的第一个字节处,也就是第一个ts包。此时方便我们查看本地的video.ts的数据。
    所以结合ts文件格式和代码,我们分析下一段代码,就是 639->643行间的 if…else…

    先来看 639行:

    if (f = !!(64 & e[a + 1]), c = ((31 & e[a + 1]) << 8) + e[a + 2], (48 & e[a + 3]) >> 4 > 1)

    好家伙,看着就懵逼的感觉。
    可以看到,if条件内,有3个语句,逗号分割,当最后一个语句为真时,就会进入if内部。
    也就是说,前2个语句,就是执行下,跟if条件没啥关系。那也得分析&#128516;

    先来看第一个语句

    if (f = !!(64 & e[a + 1]), c = ((31 & e[a + 1]) << 8) + e[a + 2], (48 & e[a + 3]) >> 4 > 1)

    叹号取反,双叹号就是负负得正。等于没有。所以只看: 64 & e[a + 1]

    我们知道a是0,那么e[a+1],显然就是video.ts的第二个字节的值。
    我们可以看到,e[1]的值也为64 , 然后再 与 64 进行与运算。
    我们把64都转为2进制(1个字节8bits, 所以补足8位)
    64:  0100 0000
    64:  0100 0000

    然后进行与运算。
    可以发现和64进行与运算的目的,就是取 取本字节8位中的左起第二位。
    该bit就是ts头中的第9位(0开始),前面我们分析过 ts头的第9位是payload_unit_start_indicator,
    即负载标志位。判断本ts包的负载数据是否是pes的起始包。
    (不理解的话,可以翻阅ts文件结构概述章节)

    因此我们可以知道
    f 即判断本ts包的数据是否是pes的起始包。(若是起始包,包含pes头)
    若是起始包,则f为1,否则0

    继续看第二个语句:


    直接翻译下:
    把 第二个字节的值 和 31 进行与运算,然后左移8位,再和第三个字节值 相加。
    分析过程省略,大家自行操作。
    上结果,c的值就是 ts头中占有13个比特的pid。
    pid代表了ts包的数据类型,可以是音频,视频、PAT、PMT或其他

    c = ((31 & e[a + 1]) << 8) + e[a + 2]
    

    此时的pid,不用看,一定是0,0代表是PAT。
    这里再介绍下PAT与PMT。
    PMT存储了媒体的目录信息,哪个视频在哪里,哪个是音频等
    PAT则是存储了PMT的信息,PMT在哪之类的。

    因此一开始一定是先解析PAT,通过PAT找到PMT,解析PMT找到我们需要的 音视频数据。

    继续看第三个语句:

    (48 & e[a + 3]) >> 4 > 1
    翻译:
    第四个字节和48进行与运算,右移4位,然后看是否大于1

    分析略,直接上结果:

    给(48 & e[a + 3]) >> 4 起个名字叫k吧,
    k的值就是 ts包头的32位占2bits的 adaptation_field_control,附加区域控制字段。
    该字段的值,用来判断附加区域是否存在,大于1 表示存在 附加域。(具体可看上一章节)

    由此,我们可以知道,只要存在附加域,就会进入if内部。
    若不存在附加域,则执行else,稍后分析。

    先来看if内部,也就是640行:

    if ((d = a + 5 + e[a + 4]) === a + 188)

    因为此时,a=0,所以简化下d的等式:
    d = 5 + e[4]   ===  188

    翻译下: ts的第5个字节值加上5。
    我们知道ts的头是4个字节,并且此时在if内部,即是存在附加域的。
    因此 我们去上一章节 看下附加域的数据格式,可以知道:
    第一个字节(8bits)代表的是adaptation_field_length, 即附加域后面的数据长度。就是此字节后面的数据长度。
    那么再加5,就表示算上 4字节的ts头长度,以及 adaptation_field_length 所占的1字节。
    也就是说 d = 5 + e[4] 的值,就是 ts头长度 和 附加域长度 之和,
    那么和188比较是为什么?  因为ts包的总长度为188,当ts头和附加域的总长度已经达到188时,就不会存在负载数据了,
    所以就不必继续分析此包,直接 continue,继续下一个包解析。

    好,接下来看看else代码,就一行,643行:d = a + 4;
    相信大家应该能猜到了。这里的4就是ts头的长度,d = a + 4,d 即表示ts负载数据的起始索引了。

    综上, 简单总结下这个if … else …

    1、f: 计算ts包的负载数据是否是pes的包的起始包。
    2、c: 计算ts包的pid
    3、判断是否存在附加域,若存在计算附加域和ts头的总长度。得到ts负载数据的起始索引d的值。
    4、若不存在附加域,则 ts负载数据的起始索引 d 的值为:包起始索引 + 4(ts头的长度)。

    结论:f表示是否是pes起始包, c代表pid, d表示ts包负载数据的起始索引。
    f、c、d 后面会一直用。 如下图:

    接下来就是 switch 语句了。

    switch (c) {
        case m:
            f && (E && (l = D(E)) && bill_appendTsData(l,d) && void 0 !== l.pts , E = {
                data: [],
                size: 0,
                bill_dataIdx:[]
     
            }), E && (E.data.push(e.subarray(d, a + 188)), E.bill_dataIdx.push(d), E.size += a + 188 - d);
            break;
        case _:
            f && (T && (l = D(T)) && bill_appendTsData(l,d) && void 0 !== l.pts, T = {
                data: [],
                size: 0,
                bill_dataIdx:[]
     
            }), T && (T.data.push(e.subarray(d, a + 188)), T.bill_dataIdx.push(d), T.size += a + 188 - d);
            break;
        case w:
            f && (A && (l = D(A)) && bill_appendTsData(l,d) && void 0 !== l.pts , A = {
                data: [],
                size: 0,
                bill_dataIdx:[]
     
            }), A && (A.data.push(e.subarray(d, a + 188)), A.bill_dataIdx.push(d), A.size += a + 188 - d);
            break;
        case 0:
            f && (d += e[d] + 1), S = R(e, d);
            break;
        case S:
            f && (d += e[d] + 1);
            var O = k(e, d, true, false);
            m = O.avc, m > 0 , _ = O.audio, _ > 0 , w = O.id3, w > 0 , p && !b && (p = !1, a = C - 188), b = !0;
            break;
        case 17:
        case 8191:
            break;
        default:
            p = !0
    }

    我们前面分析知道 c 就是pid, 因此,switch,就是根据pid来进行解析不同数据包。

    看下 switch的case值:
    case m: , case _: , case w: , case 0:, case S:, case 17:, case 8191: , defalut:
    只有 m 、_ 、w 、 S ,4个变量的未知。

    我们知道此时 c的值是0, 会进入 case 0 分支的代码,
    此处是解析PAT,S = R(e, d); 得到S的值。

    看S分支的代码,我们可以看到其中会给 m,_,w 3个变量赋值,其实S是解析PMT。

    PMT解析完,就得到了 其他3个case 分支的值,我们继续看其他 case m,_,w 分支的代码,
    非常像,只是变量不同。通过分析知道,此3个分支就是解析加密数据的部分。在此不再叙述。

    接下来就分析这3个分支的一个, 就选第一个case m

    直接在case m 分支内部第一行打断点,即646行,其他断点全部过掉,然后继续执行。程序停在了646行。

    分析下变量的值:
    首先分析:f,表示是否是pes起始包。 此时的f的值一定是 1(true),为什么?
    因为我们是第一次进入m分支,说明我们第一次解析pid为m的类型ts包,第一次解析此包,说明它一定是pes的起始包。
    所以 f 一定是1, 结合上一章节pes包在ts包中的装载格式,就会明白,pes的包被分割到不同的ts中,
    那么切割到第一个ts 包中的pes数据,一定包含pes的包头,所以该ts的 f 值一定是1 。如下图:

    f 是1 ,就会继续执行f后面的代码。

    接下来一行一行分析下 case m 的代码。bill_开头的代码,暂时过滤,是解密用的。

    case m:
        f && (E && (l = D(E)) && bill_appendTsData(l,d) && void 0 !== l.pts , E = {
            data: [],
            size: 0,
            bill_dataIdx:[]
     
        }), E && (E.data.push(e.subarray(d, a + 188)), E.bill_dataIdx.push(d), E.size += a + 188 - d);
        break;

    有两个语句以逗号分割,两个语句之间是依次执行。

    分析语句1:
    f && (E && (l = D(E)) && bill_appendTsData(l,d) && void 0 !== l.pts , E = {
            data: [],
            size: 0,
            bill_dataIdx:[]

        })

    翻译以下:
    当 f 为真时, 若E 有值,则执行 (l = D(E)) && bill_appendTsData(l,d) && void 0 !== l.pts,并给E重新赋值
                            若E 为空,则直接给E赋值
    当 f 为假时, 后面代码不会执行,语句1结束

    这里 l = D(E), 此代码将加密的PES数据解密,返回给l

    分析语句2:
    无论语句1如何执行,语句2都会执行。

    E && (E.data.push(e.subarray(d, a + 188)), E.bill_dataIdx.push(d), E.size += a + 188 – d);

    若E 为真,则给E的data添加 e的索引d到a+188之间的数据, 给E的size累加值: a + 188 -d ,这是刚才添加数据的长度。
    若E 为空, 则结束

    我们知道 d是 ts包负载数据的起始索引,d > a, a是ts包的起始索引。所以 e.subarray(d, a + 188),这个数据,就是ts包的负载数据。

    因此语句2的目的就是:将ts包的负载数据添加到 E.data中,同时记录下添加的数据的总大小。

    我们将语句1和2一起翻译下:

    当f为真时,即ts包负载是pes的起始包,若E为存在值,则直接去解密E的数据,返回给l,
    接下来则给E重新赋值,然后将此时ts的负载数据,添加到E.data中,并记录总大小size

    当f为假时,即ts包负载不是pes的起始包,将此时ts的负载数据,添加到E.data中,并记录总大小size

    我们可以发现规律,只有当 f 为真时且E数据存在,会去解密pes数据,且解密的数据是 f为假时, 添加到E.data中的数据。

    由此,我们可以得出,加密的数据是一个完整的PES数据,(PES头未加密,需要在pes解析中分析才能知道)。且这些PES数据存在于多个ts包中。

    接下来分析PES解密函数:l = D(E)

    在此函数的第一行,即:457行,打断点,删除其他断点,继续执行。会停留在此处。

    查看下传进来的参数t的值,其实就是上个函数的E的值,发现有size与data。
    其中data即pes的数据,data是个数组,数组内的元素其实是 存在于各个ts包中的pes数据。看图:

    直接断点到493行,在这里我们分析下 c 的值,这个比较重要。

    在476行, c = a + 9, a = r[8] , r = u[0], u其实就是我们的传进来的t.data
    我们观察下u[0]的数据,发现开头的三个值是 0 0 1, 这3个值是 0x 00 00 01,表示PES包的开始。
    所以u[0], 就是第一个ts包的负载,也就是包含pes包头的负载数据。

    也就是说,r = u[0]的数据中是有pes头数据的。
    结合我们上一章节的PES头数据格式,分析下a = r[8], 可以知道r[8]就是PES中占8bits的,PES头中后
    面数据长度的字段。也就是说,r[8]的值就是PES头中,此字段后面的数据的长度。

    那么 c = a + 9, 其实就是 PES头的总长度。此处c的值为31。

    因为r[8]字段的值代表PES头后面剩余数据的长度,
    加上本字节以及之前字节的长度,所以就是PES头的总长度了。

    接下来继续分析:
    将断点设在518行,继续执行,程序停留在518行。
    查看下o的值、长度,以及t.data的第一个的值,对比下。看图:

    可以看到o的值比t.data的总长度少了 31,就是c的值。
    再看o的值与t.data[0]的数据从第31个索引开始,是不是完全相同了。

    说明上面497行的for循环做的事就是:将PES的数据合并到一起,并去除PES头的数据。o便是结果。

    for (var b = 0, g = u.length; b < g; b++) {
        r = u[b];
       [/b] var v = r.byteLength;
        if (c) {
            if (c > v) {
                c -= v;
                continue
            }
            r = r.subarray(c), v -= c, c = 0
        }
        o.set(r, e), e += v
    }

    再看518行:o = startAES(o);
    此代码就是将 去除PES头的数据进行解密。得到解密后的数据。

    本函数将解密后的PES数据返回。进行下一步处理。

    由此我们知道,此ts的加密方式是对每个pes的负载数据(去除pes头)进行加密的。

    至此,ts的加密逻辑分析完成。
    总结下:

    1、程序首先加载ts数据
    2、每188个字节的循环,解析ts包
    3、根据包的数据类型(pid判断),去进行不同的解析。
    4、先解析PAT、得到PMT、得到其他媒体数据音视频等
    5、将存在于多个ts包中的pes包的数据以及总大小,保存至变量。
    6、将取得的PES包的数据和大小,传递给pes解析函数
    7、解析函数将所有pes数据组装到一起并去除PES头
    8、将组装的后的 pes数据,传给AES解密函数进行解密
    9、得到解密后的PES数据,返回给播放器

    我们现在知道了ts的数据是如何解析的,数据是在哪里解密的,以什么形式加密的。
    那么接下来就来分析下,我们如何对ts文件进行解密。

    四、如何进行解密

    聪明的你,估计已经想到了。既然我们在上一章节拿到了解密数据,那么把解密数据,替换掉加密数据,然后重新保存ts,不就ok了吗

    我只能说,聪明!!!

    先分析下思路:
    我们已知道 加密数据存在于多个ts包中,将多个ts中的数据提取,然后整和,再去解密,得到解密的整和数据。

    所以,我们就要将 解密后的数据 进行拆分 到多个ts中。

    得到解密的数据: 多个ts包 –> 得到待解密的pes –> 得到解密的数据

    将解密数据还原: 解密的数据 –> 拆分到解密数据 –> 复原到多个ts包中

    如何拆分解密的数据?
    根据解密时,传递进来的整和的pes数据的size来进行拆分。

    如何复原到ts包中?
    记录解密时,获取pes数据时,pes数据所在的索引。
    根据索引将相应的数据替换ts中的数据。

    下面来具体操作:
    1、首先在ts中提取pes数据时,记录下提取数据的索引。
    因为此时记录的索引是包含PES的头的长度。实际的解密数据是不包含PES头的。
    所以我们要把索引传递到pes解析函数中,因为只有在pes解析函数中,才能拿到pes头的长度。
    拿到pes头的长度后,把有pes包头的 的数据的索引值去掉pes头的长度。

    上代码,在所有提取pes数据的地方,添加索引数组,并记录提取pes数据的索引。看图:

    2、接下来在解析pes的函数中,对得到的pes解密数据进行拆分。

    其实拆分与组合是类似,方向相反。根据传进来的pes数据的大小,以及ts包的数量来拆分。

    拿到解密的数据,拆分后,将数据保存,同时将第一个含有pes头的索引加上pes头的长度。

    将索引和拆分的数据,一同随其他数据返回。

    每解析一个pes,我们就替换一个原始的未解密的pes数据。看图:

    3、在解析ts的append函数中,收到拆分了解密的PES数据以及索引后,开始替换ts的原加密数据。

    先看下解密的数据替换的函数:

    function bill_appendTsData(nd, idx) {
        //idx 没有用到,可忽略
         
        var i = 0,j = 0;
        let dataArr = nd.bill_pd.data;
        let idxArr = nd.bill_pd.dataIdx;
        let len = dataArr.length;
        if( len != idxArr.length ) {
            console.log('数据索引与数据数量不同');
            return;
        }
         
        for( i = 0; i < len; i++ ) {
            let darr = dataArr[i];
            let didx = idxArr[i];
             
            for ( j = 0; j < darr.length; j++) {
                bill_d[didx+j] = darr[j];
            }
        }
    }

    其实很简单,根据拿到的解密的数据和数据在ts文件的索引,替换相应的数据。
    这里打了个断点,看下接收到的拆分后的解密数据以及索引。

    这是替换函数,看下在哪里调用替换函数。在收到解密的pes数据后,紧接着就调用。
    此外,当for循环结束后,还需要对3个类型的ts包的数据,进行解密一次。
    为什么这么做?大家思考啊

    至此,PES解密分析就完成了。

    五、总结以及demo

    demo源码和示例视频,我上传到网盘了,下图为demo示例

    总结
    1、在某代码中,js函数如果不写返回值,竟然不会返回。之前代码正常。
    2、关于ts包和pes包的关系,理解了很久,最后结合代码和文章,才弄清楚最终逻辑,有些文章内容是错的,会带跑偏。
    3、对于代码中ts头和pes头的分析,也思考了很久,有时候半天想不明白。
    4、对于ts数据格式,什么PAT等等各种表,懵逼的狠。也是结合代码,总算梳理明白了。
    5、文章写了3天,梳理ts的知识,梳理代码,准备素材,再整理成文,期望对大家有所帮助。
    6、因本人水平有限,文中若有错误之处,还望各位批评指正,共同进步。

  • DiscuzX3.4论坛火车头采集器免登陆发布模块(带测试接口)

    DiscuzX3.4论坛火车头采集器免登陆发布模块(带测试接口)

    解压后看到的文件有:


    其中discusX3.0.wpm 是发布模块,dz测试接口.ljobx 是用于测试的规则,以后不要问规则该怎么写了,就按照这个格式写。

    1,上传接口

    根据自己的网站编码选择GBk或者utf8文件下下面的接口文件,jiekou.php,这个接口有个密码,默认是123456,如果想要修改,就打开这个jiekou.php,修改:


    就是上图这个,把默认的“123456”修改成你想要的,修改好了一定要保存,看不懂那就不要修改了。

    然后把这个文件上传到DZ网站的根目录,不知道什么是根目录的自己百度,不要问上传到那里,自己的网站

    别人怎么知道你的根目录是什么,不知道就自己去查。

    然后我们在浏览器里试试能不能访问,访问地址是http://网站域名/jiekou.php?pw=密码, 这个密码就是上面说的接口密码:


    如果能出现论坛的模块就证明接口是对的了。

    2,导入发布模块

    点击发布按钮:


    成功导入后会有提示的。

    发布模块设置:


    第一步,选择我们刚才导入的dz发布模块。

    第二步:全局变量就是上面说的接口文件密码

    第三步:选择对应的编码

    第四步:网站根目录就填写上面我们访问接口的时候去掉后面的接口文件名称,剩余后的地址。然后选择“不需要登录&Http请求”

    第五步:点击获取列表,如果能显示论坛版块就说明上面4步设置的正确。

    设置好了点击测试配置,成功后就设置一个配置名保存这个配置在规则里面使用,

    简单分布,只发布标题内容回复的情况

    我们打开发布模块,来介绍下里面的内容:

  • 高铁火车头采集器破解版

    高铁火车头采集器破解版是一款非常好用很受大众喜爱的网络数据采集整理软件。这款软件几乎是所有的网页都可以采集,所涉及的范围非常的广,无论是什么语言还是编码,而且这款软件能力非常的强大。它的收集速度是普通收集器的7倍之多,其中采用了最顶级的配置系统以及经过制作方的反复性能优化,让用户的采集采集速度快到飞起。用户还可以批量的进行任务处理。大大的提高工作效率。有需要的用户快来下载体验吧!

  • 小说站94采集器安装视频教程

    小说站94采集器安装视频教程

    前言

    在使用杰奇CMS建小说站的同时,往往会配套使用关关采集器进行采集小说内容,但是关关采集器需要安装在windows系统上,如果想长期建设和维护小说站,对windows系统配置(cpu、内存、硬盘)是有一定的要求,前期投入费用不低。

    本文介绍的94采集器是一款杰奇Linux系统采集器,即可以安装在linux上,这样能实现将杰奇CMS和采集器同时安装在Linux上。如果你有一台Linux主机,现在就可以建立自己的小说站啦。

    你也可以看看这篇文章,使用杰奇CMS建立小说站对服务器的要求。

    什么配置服务器适合做杰奇CMS小说站 - 长江技术博客
    什么配置服务器适合做杰奇CMS小说站 - 长江技术博客

    下面开始正题,教大家在Linux上安装94采集器。

    安装视频教程

    见顶部

    上传94采集安装包

    1)下载最新版本94采集器,上传至Linux服务器(94采集器下载在文章底部)

    先在自己的Linux上安装宝塔面板,用宝塔面板管理;

    将下载的94采集器压缩包上传到服务器上(路径可以自己定)并解压

    2)找到config.py文件,修改

    只修改端口,94采集器作者反馈其他的不需要修改;端口可以自己定义,只要不被占用即可

    图片[1] - 小说站94采集器安装教程-杰奇CMS采集 - 长江博客
    94采集器文件修改

    宝塔安全组放通

    登录宝塔面板–》安全,将上面设置的端口放通

    图片[2] - 小说站94采集器安装教程-杰奇CMS采集 - 长江博客
    宝塔面板端口放通

    安装设置python管理器

    注意:如果你宝塔面板中的安全加固功能开启了,请先关闭,不然管理器启动会失败

    1)使用宝塔安装python管理器,并利用管理器安装python3.8.5版本

    图片[3] - 小说站94采集器安装教程-杰奇CMS采集 - 长江博客
    图片[4] - 小说站94采集器安装教程-杰奇CMS采集 - 长江博客

    2)添加项目管理

    参考下发截图设置

    图片[5] - 小说站94采集器安装教程-杰奇CMS采集 - 长江博客

    3)启动失败问题

    启动失败问题,查看日志,提示缺少cfscrape,解决方法如下:

    图片[6] - 小说站94采集器安装教程-杰奇CMS采集 - 长江博客

    到此,94采集器安装完成。

    94采集器登录

    使用Linux的ip加端口的方式登录,如:http://x.x.x.x:9098

    默认的登录用户名和密码在config文件;如果修改用户名和密码,修改之后需要重启python项目

    图片[7] - 小说站94采集器安装教程-杰奇CMS采集 - 长江博客
    九四采集器登录页面

    如果还有安装问题,可读取这篇文章,下载视频教程。

    94采集器下载地址

    [b2_insert_post id=”3172″]

    当然,如果现有的94采集器无法满足你的要求,你还可以下载 94采集器来修改源码达到自己的目的。

    94采集器源码下载地址

    [b2_insert_post id=”3748″]

  • 小说站94采集器之添加任务(图文+视频)教程

    1 概述

    94采集器支持单书号文章采集、书号列表采集、分类列表采集等方式,可以实现对目标站全量、分批采集,完全可以满足个人运营采集的需求。

    2 添加任务视频教程

    见上面视频

    3 任务参数配置

    主要参数说明

    任务ID:空白,后期生成会自动补数据
    规则ID:选择采集规则
    任务名称:随便写
    间隔时间:这里的单位是秒,数据太小,会导致采集源站屏蔽,一般600-1800秒
    添加类型:有四个选项,一般默认选“添加” 正常采集
    默认、书号、书号列表、列表:这个选择是根据你规则来选择和配置的,这里我们的规则是按照列表来采集的,所以图片中我们只配置了列表,具体设置可以参考自己规则配置。
    封面更新:否
    简介更新:否
    标识修复:是
    字数修复:1000
    采集间隔:0.1-10
    重试次数:5-60
    重试间隔:1-30
    最低章节数:2 章节数低于2章节的不采集
    最高章节数:10000 章节数高于10000章节的不采集
    UserAgent:直接选择,因为在配置系统参数的时候已经加入了
    对比方式:最后章节名称 按需选择
    小说线程数/章节线程数:根据服务器配置写,我是1H1G的测试vps 所以写1-2
    代理信息设置:如果用代理 这里设置
    过滤信息设置:如果有不想采集的小说名称,写这里

    添加书号类型任务

    QQ20220615205824-1024x414-1
    书号类型任务参数设置

    添加书号列表类型任务

    QQ20220615210056-1024x412-1
    书号列表任务参数设置

    添加列表类型任务

    QQ20220615210325-1024x406-1
    列表任务参数设置

    任务启动,成功采集

    QQ20220615210916-1024x194-1

    小说站94采集器的主要教程暂时就介绍到这里,其他功能大家可以自己测试。整体上来说从安装到设置,再到最后的采集,94采集器的设置还是比较简单的。

    注意事项

    • 采集后没有数据或者章节内没有内容:查询txt路径是否正确
    • 采集后图片不显示:排除模板原因的话,查询img路径是否正确
    • 采集后章节内容不换行:采集规则问题,使用<p>替换 或者/n替换,不要使用</br>替换
    • 采集突然中断:请修复杰奇cms数据库,切记使用杰奇后台修复
  • 小说站94采集器之系统设置(图文+视频)教程

    小说站94采集器之系统设置(图文+视频)教程

    之前讲解了94采集器的安装,从本文开始讲解94采集系统的设置,指导大家一步步实现linux系统下的杰奇cms小说采集。

    图片[1] - 小说站94采集器之系统设置(图文+视频)教程 - 长江技术博客
    94采集器设置管理

    1 系统设置视频教程

    见上方视频

    2 数据库设置

    根据自己的杰奇cms小说网站的数据库信息进行设置,如下截图所示:

    图片[2] - 小说站94采集器之系统设置(图文+视频)教程 - 长江技术博客

    3 系统设置

    图片[3] - 小说站94采集器之系统设置(图文+视频)教程 - 长江技术博客

    注意:文本格式根据自己小说站模板的格式来进行设置

    图片[4] - 小说站94采集器之系统设置(图文+视频)教程 - 长江技术博客

    4 分类设置

    包含大类设置(一级分类)和小类设置(二级分类),其实和使用关关采集器设置分类差不多:

    1=玄幻小说,玄幻魔法,玄幻,玄幻奇幻,玄幻魔法,异陆,魔法,异能,玄幻小说,东方玄幻,异界大陆,玄幻仙侠,魔法奇幻,魔幻,玄幻,魔法,玄幻魔法,异陆,奇幻,奇幻-异界幻想,奇幻-仙侠情缘,奇幻-妖精灵怪,奇幻-西方魔幻,奇幻-吸血家族,玄幻小说,重生文学,奇幻小说,玄幻异界,奇幻魔法,东方玄幻,异世大陆,王朝争霸,高武世界
    2=修真小说,武侠修真,武侠,武侠仙侠,武侠修真,修真,仙侠,仙侠修真,武侠小说,仙侠小说,远古神话,修真小说,古典仙侠,洪荒封神,女生武侠,恩怨情仇,仙侠,修真文明,幻想修仙,现代修真,神话修真
    3=都市小说,都市言情,都市,都市小说,都市言情,都市生活,言情,言情小说,台湾言情,都市异能,都市激战,官场风云,青青校园,都市官场,爱情婚姻,都市生活,都市异能,异术超能,青春校园,娱乐明星,都市娱乐
    4=穿越小说,历史,军事,历史军事,战争,战争小说,历史小说,军事小说,历史穿越,战史风云,谍战特工,架空历史,军史传奇,前世今生,家宅布衣,穿越,架空,古言,历史,历史古代,穿越小说,历史军事
    5=网游小说,游戏,游戏竞技,网游竞技,网游,游戏小说,网游动漫,网游小说,竞技小说,动漫小说,游戏异界,虚拟网游,动漫,网游,电子竞技,虚拟网游,游戏异界,游戏主播
    6=科幻小说,科幻,科幻小说,科幻-未来世界,科幻小说,科幻灵异,古武机甲,未来世界,星际文明,超级科技,时空穿梭,进化变异,末世危机,科幻末日,科幻空间
    7=女频小说,豪门世家,恩怨情仇,婚恋爱情,职场丽人,婚恋爱情,言情耽美,女生频道,女生,女频小说,女生频道,纯爱,情感,校园,耽美言情,现言,爱情,同人,女生言情,耽美百合,幻想言情,浪漫青春
    8=灵异小说,恐怖小说,惊悚小说,恐怖,惊悚,灵异小说,灵异,悬疑灵异
    9=次元小说,N次元,同人动漫,主角小说
    10=其他类型,其他,其它,其他小说,其它小说,其他类型,其它类型,综合其他

    就是一些1对多的映射关系,等号左边个人网站的分类id,等号右边可以根据目标网站进行调整。

    5 频道设置

    1=男
    2=女

    同样,左边根据你自己网站进行设置,等号右边可以根据目标网站进行调整。

    6 连载状态设置

    0=连载中
    1=已完结

    同样,左边根据你自己网站进行设置,等号右边可以根据目标网站进行调整。

    7 标识设置

    采集的目标站文章中,如果匹配到了如下设置信息,文章会被进行标识,那么后续再进行采集更新就会修复这些章节

    图片[5] - 小说站94采集器之系统设置(图文+视频)教程 - 长江技术博客

    8 UA设置

    就是访问的浏览器标识,必须设置;可以直接使用如下:

    Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36
    Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 Edg/92.0.902.62
    Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
    Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Mobile Safari/537.36
    Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Mobile Safari/537.36 Edg/92.0.902.62

  • 小说站94采集器之采集规则编写(图文+视频)教程

    小说站94采集器之采集规则编写(图文+视频)教程

    94采集器的系统配置完成后,接下来就是采集规则编写,利用采集规则对目标站进行采集。

    1 概述

    可以直接导入已有的采集规则,也可以自己编写新规则;采集规则有两种编写方式,分别是正则规则和CSS规则。

    2 采集规则编写视频教程

    最上面。

    3 手工导入已有规则

    94采集器系统中,规则列表栏目下,直接点击“导入”即可,本文提供了几个已有的规则供大家下载(附件)。

    图片[1] - 小说站94采集器之采集规则编写(图文+视频)教程 - 长江技术博客

    4 新规则编写

    94采集器系统中,规则列表栏目下,直接点击“添加”,规则每个参数都有详细的描述(如下截图),CSS规则和正则规则的具体写法,可以通过视频教程学习。

    图片[2] - 小说站94采集器之采集规则编写(图文+视频)教程 - 长江技术博客

    另外,点击系统右上角的感叹号,可以弹出常用的CSS规则集合,按照作者的说法,这些规则几乎匹配99%的笔趣阁小说站模板。

    图片[3] - 小说站94采集器之采集规则编写(图文+视频)教程 - 长江技术博客

    注意,有些站开启了防采集功能,就不要采集了。

  • 网站安全设置-苹果CMS安全设置教程

    网站安全设置-苹果CMS安全设置教程

    网站安全是网站搭建运营过程中非常重要的一部分,需要对服务器、网站进行一定的安全设置,减少黑客入侵的机会。若网站遭到DDOS、黑客攻击、被挂马跳转等,数据会被盗窃或者毁坏,会影响到收录和权重。本文记录苹果CMS做站过程中遇到的或了解到一些场景,针对性的做好安全防护。

    图片[1] - 网站安全设置-苹果CMS安全设置教程 - 长江博客

    1)苹果CMS程序、模板后门

    模板程序,建议从正规途径下载(很多资源站下载的模板程序 最好站长测试过),模板程序带后门,这种情况是最常见的。

    模板使用前,可以尝试使用工具“D盾”扫描下。

    2)服务器密码、程序后台登录密码、数据库密码

    建议使用复杂密码、并且定期修改。

    在设置网站密码时,尽量设置复杂些,现在密码一般有10个以上字符,且由数字和符号以及大小写字母组合而成,网站密码不要和电子邮箱或社交媒体账户相同。

    3)使用了一些插件带有后门

    不建议使用任何插件,没有百分百可靠的,之前有用过“萌芽”采集插件,网站出现跳转,删除后立即恢复正常。

    4)权限设置

    5)使用宝塔防篡改工具

    宝塔安装“网站防篡改”程序,避免网站程序被篡改,安装之后程序、模板就不会被篡改掉。(注意在修改苹果CMS后台配置过程中,需先关闭防篡改,不然修改配置保存不生效)

    图片[2] - 网站安全设置-苹果CMS安全设置教程 - 长江博客

    6)网站路径下不要放置任何压缩包

    网站根路径下不要放置任何压缩包,有些站长会将网站压缩备份在网站根路径下面,会被别人扫描出来。

    7)苹果cms路径下的user文件夹

    检查/upload/user文件夹下是否存在一些异常文件,用户可以上传头像到这个文件夹进行渗透,懂渗透可以加代码提权篡改。

    8)nginx配置

    小编之前遇到过,网站被挂马,检查发现网站nginx配置文件中被挂马了

    图片[3] - 网站安全设置-苹果CMS安全设置教程 - 长江博客
    网站nginx配置文件

    9)nginx模块

    之前有遇到一种情况,服务器上所有网站都会偶发性的跳转,网站程序初步排查后没有问题,怀疑是服务器遭受ARP攻击或者服务器环境出了问题,最后把nginx版本从1.18升级到1.21后,跳转就没有了,应该是nginx的哪个模块出了问题。

    总之,保护网站的安全,要做的事情还有很多,如访问安全网站、不明来历的链接不要点击、租用正规、安全性高的主机空间等,这里就不详细叙述了。对于网站管理员来说,能做的事情一定要及时去做,千万不要嫌麻烦,希望广大站长能通过以上几点或其它方式来有效防护好网站的安全。

  • 94采集器5.2.4源码(注意是源码)

    94采集器5.2.4源码(注意是源码)

    94采集器本身功能相对于关关来说还是弱了不少,但因为可以运行在Linux上这一点特质,使得很多站长趋之若鹜,但是94采集器已经很久没有更新了,作者也不知道哪里去了。如果想改点功能或者增加点什么功能或者fix什么bug都成为妄想。

    无错源码今天提供的是94最后发布的5.2.4版本,相信可以帮助有需要的人解燃眉之急,毕竟源码在手,天下我有。

    照例先看下截图吧

    94的作者是少见的拿中文来写代码的作者,怎么说呢,就感觉这代码看着很亲切又很遥远。。。。。

    需要的筒子们自取吧。

    关于94采集器的安装,请参见以下这篇文章

    [b2_insert_post id=”3172″]

  • JSJIAMI V7 最新解密工具

    JSJIAMI V7 最新解密工具

    JSJIAMI的作者好像除了会吹牛也没有什么其它本事了。。。。。

    每次新版本出来都说自己加密算法牢不可破,每每被打脸,真的很无语。

    其它,javascript这种前端语言,无论你怎么加密,最后都是要被脱裤子的。

    今天分享一个最新的jsjiami v7版本的解密工具。

    老套路:先看V7加密前的源代码。

    (function(w, d) { 
    
     w.update = "2023年7月16日05:34:29更新"; 
    
     d.info = "本站历时1年半研发的新版本V7初版,具有多态性加密,破解难度更高。"; 
    
     d.feedback = "由于刚刚上线,有问题积极反馈,请联系QQ 11223344"; 
    
     d.tips = "如遇不兼容,请先暂时用v6加密,并反馈给我们。"; 
    
    })(window, document);

    我们直接在jsjiami的官网给他进行加密

    加密后的代码如下

    /*
     * 加密工具已经升级了一个版本,目前为 jsjiami.com.v7 ,更新了加密算法,缩减了体积;
     * 另外 jsjiami.com.v7 已经强制加入校验,注释可以去掉,但是 jsjiami.com.v7 不能去掉,其他都没有任何绑定。
     * 誓死不会加入任何后门,JsJiami.com 加密的使命就是为了保护你们的Javascript 。
     */
     var version_='jsjiami.com.v7';(function(_0x5002d1,_0x5f4aa0,_0x21acac,_0x378094,_0x3bf05d,_0x1281b6,_0x1624a5){return _0x5002d1=_0x5002d1>>0x6,_0x1281b6='hs',_0x1624a5='hs',function(_0x5cbc36,_0x5b6dd5,_0x2fc331,_0x523dae,_0xd0f20d){var _0x5a5a5a=_0x2cd7;_0x523dae='tfi',_0x1281b6=_0x523dae+_0x1281b6,_0xd0f20d='up',_0x1624a5+=_0xd0f20d,_0x1281b6=_0x2fc331(_0x1281b6),_0x1624a5=_0x2fc331(_0x1624a5),_0x2fc331=0x0;var _0x1d1aa8=_0x5cbc36();while(!![]&&--_0x378094+_0x5b6dd5){try{_0x523dae=-parseInt(_0x5a5a5a(0x101,'2z2L'))/0x1+-parseInt(_0x5a5a5a(0x110,']x6^'))/0x2+-parseInt(_0x5a5a5a(0x102,'%Uvw'))/0x3*(-parseInt(_0x5a5a5a(0x10f,'Qano'))/0x4)+parseInt(_0x5a5a5a(0x103,'*M8d'))/0x5*(parseInt(_0x5a5a5a(0xfe,'5a#$'))/0x6)+-parseInt(_0x5a5a5a(0xfc,'3YC5'))/0x7+parseInt(_0x5a5a5a(0x109,'HH(n'))/0x8+parseInt(_0x5a5a5a(0xfa,'FRel'))/0x9*(parseInt(_0x5a5a5a(0x108,'HH(n'))/0xa);}catch(_0x3e2001){_0x523dae=_0x2fc331;}finally{_0xd0f20d=_0x1d1aa8[_0x1281b6]();if(_0x5002d1<=_0x378094)_0x2fc331?_0x3bf05d?_0x523dae=_0xd0f20d:_0x3bf05d=_0xd0f20d:_0x2fc331=_0xd0f20d;else{if(_0x2fc331==_0x3bf05d['replace'](/[ISLQpueHXdyGKDEMqhTC=]/g,'')){if(_0x523dae===_0x5b6dd5){_0x1d1aa8['un'+_0x1281b6](_0xd0f20d);break;}_0x1d1aa8[_0x1624a5](_0xd0f20d);}}}}}(_0x21acac,_0x5f4aa0,function(_0x19788d,_0x1ccf28,_0x14321e,_0x3197ff,_0x12b5b8,_0x3371c0,_0x1c9ef8){return _0x1ccf28='\x73\x70\x6c\x69\x74',_0x19788d=arguments[0x0],_0x19788d=_0x19788d[_0x1ccf28](''),_0x14321e='\x72\x65\x76\x65\x72\x73\x65',_0x19788d=_0x19788d[_0x14321e]('\x76'),_0x3197ff='\x6a\x6f\x69\x6e',(0x134f3a,_0x19788d[_0x3197ff](''));});}(0x3280,0x32366,_0x2099,0xcc),_0x2099)&&(version_=_0x2099);function _0x2cd7(_0x5f8b48,_0x4c46ef){var _0x20998f=_0x2099();return _0x2cd7=function(_0x2cd77b,_0x3f633c){_0x2cd77b=_0x2cd77b-0xfa;var _0x67ef06=_0x20998f[_0x2cd77b];if(_0x2cd7['nfRiKE']===undefined){var _0x412be3=function(_0x16570f){var _0x92b478='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x4f3209='',_0x586c05='';for(var _0x3497c0=0x0,_0x51756a,_0x5cd8e8,_0x1b668e=0x0;_0x5cd8e8=_0x16570f['charAt'](_0x1b668e++);~_0x5cd8e8&&(_0x51756a=_0x3497c0%0x4?_0x51756a*0x40+_0x5cd8e8:_0x5cd8e8,_0x3497c0++%0x4)?_0x4f3209+=String['fromCharCode'](0xff&_0x51756a>>(-0x2*_0x3497c0&0x6)):0x0){_0x5cd8e8=_0x92b478['indexOf'](_0x5cd8e8);}for(var _0x1ab439=0x0,_0x505f90=_0x4f3209['length'];_0x1ab439<_0x505f90;_0x1ab439++){_0x586c05+='%'+('00'+_0x4f3209['charCodeAt'](_0x1ab439)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x586c05);};var _0x3274ed=function(_0x1faa60,_0x43cfdb){var _0x566996=[],_0x2ac031=0x0,_0x49ffa1,_0x35152e='';_0x1faa60=_0x412be3(_0x1faa60);var _0x3c4505;for(_0x3c4505=0x0;_0x3c4505<0x100;_0x3c4505++){_0x566996[_0x3c4505]=_0x3c4505;}for(_0x3c4505=0x0;_0x3c4505<0x100;_0x3c4505++){_0x2ac031=(_0x2ac031+_0x566996[_0x3c4505]+_0x43cfdb['charCodeAt'](_0x3c4505%_0x43cfdb['length']))%0x100,_0x49ffa1=_0x566996[_0x3c4505],_0x566996[_0x3c4505]=_0x566996[_0x2ac031],_0x566996[_0x2ac031]=_0x49ffa1;}_0x3c4505=0x0,_0x2ac031=0x0;for(var _0x1a42d6=0x0;_0x1a42d6<_0x1faa60['length'];_0x1a42d6++){_0x3c4505=(_0x3c4505+0x1)%0x100,_0x2ac031=(_0x2ac031+_0x566996[_0x3c4505])%0x100,_0x49ffa1=_0x566996[_0x3c4505],_0x566996[_0x3c4505]=_0x566996[_0x2ac031],_0x566996[_0x2ac031]=_0x49ffa1,_0x35152e+=String['fromCharCode'](_0x1faa60['charCodeAt'](_0x1a42d6)^_0x566996[(_0x566996[_0x3c4505]+_0x566996[_0x2ac031])%0x100]);}return _0x35152e;};_0x2cd7['FldXek']=_0x3274ed,_0x5f8b48=arguments,_0x2cd7['nfRiKE']=!![];}var _0x424401=_0x20998f[0x0],_0x15e8f3=_0x2cd77b+_0x424401,_0x102d5f=_0x5f8b48[_0x15e8f3];return!_0x102d5f?(_0x2cd7['EJEGxI']===undefined&&(_0x2cd7['EJEGxI']=!![]),_0x67ef06=_0x2cd7['FldXek'](_0x67ef06,_0x3f633c),_0x5f8b48[_0x15e8f3]=_0x67ef06):_0x67ef06=_0x102d5f,_0x67ef06;},_0x2cd7(_0x5f8b48,_0x4c46ef);}function _0x2099(){var _0x5d7835=(function(){return[version_,'djTQsHDjXXiGaqXmdiEK.SpcCyMoXmhIE.evMu7L==','uSoTjKpdTmkBWO0IW5RdHSoSWPG','taDEW5bnW7CJaIVcGq','W4FdUwPRW7NcLvFcSSklxSkCdW','5Awj6yov5lUr5yEg5A+b77+66k6W5yE25PM15PsA55A5lSkN5yIv5A6R77Yq5BQ95yYl6AwM57Mg5OMk5lIo44c/','W6tdVmk/dMZcT8kQWQJdSCoOW54','W77cPSkPW5qwWPqqW5q','W58anZmgWO5yW4z1WOhcLCo/'].concat((function(){return['kmkHlSoNxXldJmktrmoJqqi','W5tcVwddOrxdLxHJ','W6xdUmk5bow4R8of5P+hW7lcRUAvMCk3qGdcTYDcmSk85PIA5Psd','WO8oWPa/W5yObvS1','kSkaW4X5WQHSW5XknZ0SCW','WOqvDuCWjmklW67dUa','a3ORlfzEm8oxWOhcL8o1WOq','WOqdWPnqWOOom3unpmov','yZvtWORcJ8kP'].concat((function(){return['BmosdmojW5njWQOf','WPxdOgxdVa','WOOzWP/cVsJcLSkomCo8','WOuEWPNdMhNdL8kJc8obW7xcPCki','W5W8sCo0W58','WP81WPhdPeLUWQHxv8kGd8kC','Emo4FSk9','55EM5lMg5yQr5yIT5lMr57Mn77+d5P+k6zw26AcK56wO5P+25y+36Asm77YF6k6p6igu57g+WR/dOSokW6FdQaJcOa7cL0O+'];}()));}()));}());_0x2099=function(){return _0x5d7835;};return _0x2099();};(function(_0x394129,_0x1eef7b){var _0x1e3e4e=_0x2cd7,_0x4b9b40={'oebqw':'本站历时1年半研发的新版本V7初版,具有多态性加密,破解难度更高。'};_0x394129[_0x1e3e4e(0x105,'xsOl')]=_0x1e3e4e(0xff,'FRel'),_0x1eef7b[_0x1e3e4e(0x10c,'YOEK')]=_0x4b9b40[_0x1e3e4e(0x10a,'@H%9')],_0x1eef7b[_0x1e3e4e(0x106,'#FO]')]=_0x1e3e4e(0x10d,'FRel'),_0x1eef7b[_0x1e3e4e(0x107,'5a#$')]=_0x1e3e4e(0x111,'vAEx');}(window,document));var version_ = 'jsjiami.com.v7';

    现在把这段加密后的代码丢到我们的解密工具中去

    看一下解密后的结果

    (function (_0x394129, _0x1eef7b) {
      _0x394129.update = "2023年7月16日05:34:29更新";
      _0x1eef7b.info = "本站历时1年半研发的新版本V7初版,具有多态性加密,破解难度更高。";
      _0x1eef7b.feedback = "由于刚刚上线,有问题积极反馈,请联系QQ 11223344";
      _0x1eef7b.tips = "如遇不兼容,请先暂时用v6加密,并反馈给我们。";
    })(window, document);

    我们可以看到,除了被混淆的变量,我们的javascript代码已经被完美的还原了,这样的js替换原有的js是可以完美运行的。

    解密大功告成。

    声明:本站解密方法严禁用于不法用途,一旦发现将封禁账号。

    虚拟物品属性特殊,售出后不退款。请思考清楚再拍。

    加密有不可预料性,不保证100%成功。