吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 16748|回复: 128
收起左侧

[Web逆向] 某东和文泉在线阅读epub解密

    [复制链接]
我是不会改名的 发表于 2022-5-12 00:26
本帖最后由 我是不会改名的 于 2022-5-12 17:37 编辑

在线阅读epub解密简单分析

参考文章:

  1. JavaScript 教程

  2. JavaScript AST其实很简单

  3. 反爬虫AST原理与还原混淆实战(微课视频版)

  4. Epub格式电子书格式解析

  5. ast自动扣webpack脚本实战

  6. 某网站webpack逆向

  7. python下载文泉学堂求助

  8. jwt

    前言

       测试的网址都比较简单,适合新手练手,我也刚学

    本文仅仅针对标准的epub格式,有兴趣可以去了解下,这里放一张图对比。仅仅涉及解密过程,不涉及下载。

    QQ截图20220429184728.png

​    温馨提示,本文内容仅做学习交流,禁止用于批量或非法爬取。如有侵犯你的权益请联系我,将于24h内删除。

某东专业版pc+h5_1

目标网站:dG9iLW0uamQuY29t,aHR0cHM6Ly9neC5qZC5jb20vZ3gvZ3hfaW5kZXguYWN0aW9u;

打开网站,随便打开一本书,按下F12,先别刷新,直接点下一章,因为这样方便定位请求的地址

QQ截图20220429190038.png

很明显请求的就是这个地址,但k后面的内容以及响应的内容貌似是加密的,先分析请求中的k值,注意前面的关键词read_chapter.action,直接搜索,很容易定位到这里,下个断点,刷新,在控制台执行一下代码

QQ截图20220429190723.png

很好就是这个,跟下去,格式化一下,点左下角{}

3f7e0f86d8c947ab3b652c725fae4e8.png

var _0xodF='jsjiami.com.v6',
*********
_0x49ac=_0xodF='jsjiami.com.v6';

jsjiami.com.v6加密的,有兴趣的看一下上面提到的ast系列文章,尝试还原一下,在附件里面我上传了混淆和还原后的js

QQ截图20220429192322.png

因为很短就直接分析了懒得替换,搜索关键词readType,定位到关键代码,下个断点,在控制台中执行关键的代码,很容易发现原始和加密后的数据

QQ截图20220429193611.png

然后又是一个混淆了的,和上面一样,不多讲了,很短没必要还原,直接看就行了

var pc1 = new PC1();
function encryption(_0x30c8da) {
    var _0x138c44 = {
        'ovOTw': _0x1ad9('5d', 'ch8w')
    };
    return pc1[_0x1ad9('5e', 'DJHM')](pc1[_0x1ad9('5f', 'N!8d')](pc1['utf16ToBytes'](_0x30c8da), pc1['stringToBytes'](_0x138c44['ovOTw']), ![]));
}
function decryption(_0x547fb5) {
    var _0x156c4 = {
        'EapRO': _0x1ad9('60', 'tlv1')
    };
    return pc1['bytesToUtf16'](pc1[_0x1ad9('61', 'qelS')](pc1['hexToBytes'](_0x547fb5), pc1[_0x1ad9('62', 'n(Db')](_0x156c4['EapRO']), !![]));
}

很明显了下面是写了一个调用上面的函数,看不懂,没关系,只需要知道,加密是函数 encryption同时传入了参数_0x30c8da(从上面可知是{"encrypt":1,"bookId":"30734545","chapterId":"90594508"}),然后干了啥,不需要知道,直接保存下来,用python调用,因为很短,逻辑很清晰可以这样,执行py,网页返回的信息,完全一样,没有问题。

QQ截图20220429195343.png

然后就是解密响应内容了,根据上面的分析,很容易发现,在加密的下面,就是解密,同样的调用js,解密内容。

decryption = context.call("decryption", content)
原始数据 {"encrypt":1,"bookId":"30734545","chapterId":"90594508"}
加密后的内容 c32bc*******c9493
返回的数据 3d7bddef9dad847e1bb12aae18 ****省略***456b9af5
解密后的内容 {"contentList":[{"content":"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?><!DOCTYPE html PUBLIC \****省略***\/html>"}]}

很明显content里面的内容就是我们所需要的,具体怎么处理转换成epub就不讲了,我也不会,可以自己了解一下epub格式。

还剩最后一个问题,chapterId,是从哪里来的,直接搜什么内容也没有,那么很明显了就是加密的,直接搜关键词chapterId,发现有很多。

但我们前面,讲了一个加密解密的方法,那么很明显,按照摸鱼三大法则,大胆猜测肯定也在这里附近,直接在加密和解密这下个断点,刷新,果然发现了和之前的不一样,原始数据没有chapterId,再继续执行,看返回后的数据解密后,果然

chapterId就在这里面,虽然名字不叫chapterId,但看长度一搜明显就是,到此关键的部分结束了。

5894d1d64f715613.png

这里分析的是H5-1,pc网页和这个是完全一样的只是名字稍微改了一下,就不多讲了。

某东专业版H5-2

测试网站:aHR0cHM6Ly9tLXRvYi5qZC5jb20vcmVhZGVydG9iL3JlYWRlcj9lYm9va0lkPTMwNjc0MDQ3

重复上面的第一步,然后定位到关键的位置

QQ截图20220429204047.png

是个webpack,有兴趣可以了解一下,同样搜索关键词,定位到关键函数

            enData: function(e) {
                var t = this.getKey(this.time)
                  , n = this.encrypt(e.split("?")[1], t, this.time);
                return e = e.split("?")[0] + "?enc=1&app=" + this.app + "&tm=" + this.time + "¶ms=" + encodeURIComponent(n)
            }

控制台执行,发现多了很多未知的参数

QQ截图20220429210236.png

先不管,后面再来解决,继续跟进

return n % 2 == 0 ? this.AESEncrypt(e, t) : this.DESEncrypt(e, t)

那么很明显了,根据上面n是时间戳,根据时间戳为奇数或者偶数分为了,AES和DES,为了方便我把时间戳写死了,写成偶数,因为不太熟悉DES。

继续执行,发现就是一个AES/ECB/Pkcs7,然后e为待加密的内容,t取md5值作为key

            AESEncrypt: function(e, t) {
                var n = U.a.enc.Utf8.parse(e)
                  , o = U.a.MD5(U.a.enc.Utf8.parse(t));#取
                return U.a.AES.encrypt(n, o, {
                    mode: U.a.mode.ECB,
                    padding: U.a.pad.Pkcs7
                }).toString()
            }

防止魔改,用其他软件实现对比一下,没有问题

QQ截图20220429211732.png

然后查看返回数据发现仍然是加密的,同样的根据摸鱼三大定律,解密部分就在加密下面,根据时间戳来判断解密方式,e为加密内容,t取md5值作为key

            AESDecrypt: function(e, t) {
                var n = U.a.MD5(U.a.enc.Utf8.parse(t))
                  , o = U.a.AES.decrypt(e, n, {
                    mode: U.a.mode.ECB,
                    padding: U.a.pad.Pkcs7
                });
                return U.a.enc.Utf8.stringify(o).toString()
            }

QQ截图20220429213313.png

那么就只剩下上面提到的一些参数了,随便搜一下,team_id是学校的编号固定的,cookie里面有,就不分析了

/jdread/api/download/chapter/30470981?app=tob-web&tm=1651292175581&team_id=*****&uuid=****&client=pc&os=web&sign=*****

搜索关键词uuid,定位到关键代码,下断点

            getUuid: function(e) {
                var t = ""
                  , n = Q.a.get("u") || "";
                return e.uuid ? t = e.uuid : (n ? localStorage.setItem("_u", n) : (n = localStorage.getItem("_u")) || (n = "h5" + this.guid(),
                localStorage.setItem("_u", n)),
                t = n),
                _e.uid || t
            }

结果发现信息在这之前就有了,无论怎么调试,一直都找不到关键位置

凭借我初中水平(因为小学没学英语)的英语注意到localStorage(本地**),说明在这之前就存入了

那么我们先清空,控制台输localStorage.clear(),刷新发现回到了登录界面,很明显了,多半就是登录的时候写入了,搜索关键词,下断点,刷新,进入关键函数

这里需要自己扣代码,或者一步步调试进入js,详情可以看看上面的webpack,关键就差不多这样,结果意外发现sign也在这里,先记住,在这里明显看出,uuid:h5+guid(),那么进入关键函数

import Cookies from 'js-cookie'
import md5 from 'blueimp-md5'
import { HOST, APP } from './global'
import { getQuery, guid, getOS } from './common'
*******
  if (url.indexOf('uuid=') === -1) {
    if (u) {
      localStorage.setItem('_u', u)
    } else {
      u = localStorage.getItem('_u')
      if (!u) {
        u = 'h5' + guid()##########
        localStorage.setItem('_u', u)
      }
*********
// 加密内容*********
  const salt = md5(app + time + uuid)
  return salt
  *********
// 加密签名
*********
  const sign = md5(salt + URI + queryString)
  *********

// WEBPACK FOOTER //
// ./src/utils/encrypt.js

发现就是最常用生成的uuid的方法,那就没什么好讲的了,自行百度吧。

import { mediaWidth } from '../config'
**********

// 生成唯一id
const guid = () => {
  function S4 () {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
  }
  return (S4() + S4() + S4() + S4() + S4() + S4() + S4() + S4())
}
**********

// WEBPACK FOOTER //
// ./src/utils/common.js

然后只剩下sign了,上面已经提到了sign加密函数,就简单看一下,首先是对取(app + time + uuid)的MD5值得到salt,app对应类型tob-web是固定的,time是时间戳,uuid就是上面提到的,为了方便同样把时间写死,然后再对salt + URI + queryString取MD5值,url和queryString自己看图,和前面的进行对比完全一样,到此所有加密参数都基本搞定了

QQ截图20220430154042.png

某学堂

aHR0cHM6Ly93cWJvb2sud3F4dWV0YW5nLmNvbS9kZWVwL3JlYWQvZXB1Yj9iaWQ9MTAzNzQx

学堂有两个部分需要解密,第一个就是,请求内容时候的k值,这里面python下载文泉学堂求助说的很清楚了,自己去看看吧。

然后呢对于pdf来说,返回的就是图片,不用解密,但对于epub来说返回的数据还是加密的,还需要继续解密,直接开搞

快速定位到相关位置,点进去。

QQ截图20220511234106.png

QQ截图20220511234155.png

一个ob混淆,而且很大,试了下一键还原的插件不行,那么自己想办法还原,整个五一加一周学了下ast。

然后准备先还原js,还原之前,先大致了解js内容,看图吧。

先分析下第一个整体结构,大致就这样。

QQ截图20220503151934.png

再分析内部的基本结构与逻辑。

QQ截图20220503160137

QQ截图20220503160633.png

QQ截图20220503155209.png

删除第一个,继续分析下一个,就简单分析一下

QQ截图20220503203734.png

QQ截图20220503204346.png

后面没啥好讲的了,基本就是平坦流,花指令啊之类的,基本可以用插件一键还原。

然后花了,整个五一假期门都没出加一周学ast,还原js,结果

R-C.jpg

QQ截图20220511174226.png

没什么好说的了,就是CryptoJS,改了下,重新分析网页

既然返回的数据是加密的,对于js来说,肯定要解析内容,转化成数组,直接搜Uint8Array,定位到解密后的函数

QQ截图20220511225014.png

运气很好,很快注意到,response以及,Uint8Array(t);,这里面创建了很多数组,注意我标注的位置,后面都有用到,唯一有一个,dpbt函数是自己写的,反混淆后长这样。

QQ截图20220511232553.png

dpbt = function(t) {
                for (var r = new Uint8Array(4), e = r.length - 1, i = t.length - 1; e >= 0; e--,
                i--)
                    r[e] = i >= 0 ? t[i] : 0;
                var n = (255 & r[0]) << 24
                  , o = (255 & r[1]) << 16
                  , a = (255 & r[2]) << 8
                  , s = 255 & r[3];
                return n + o + a + s
            }

其实,对于解密epub来说,可以看出来,o始终是定值,那么a也始终是定值48,很容易想到16+32,大胆猜测,算了继续看下去吧。

继续跟进,来到了今天的正题。

首先传进来了几个值,t就是上面的l,n是上面的f,i是CryptoJS,其余两个没啥用。然后就开始了两次AES/ECB解密,第一次就用到了前面提到的16+32,第二次就用第一次解密后的内容作为key解密epub内容,但要注意解密的并不是全部返回数据,而是去掉了前十位后的数据再解密,至此解密完成了。

QQ截图20220511230839.png

再用软件还原对比一下,防止魔改。

QQ截图20220511235636.png

很好,没有问题,到此全部结束了,原本还打算继续加一个圣才(很简单)和可知(很麻烦)的,是在没时间了,看后续有时间再继续写。

大部分内容能给的都上传到附件了,就别问我了,没写下载软件也不会。

附件

免费评分

参与人数 49威望 +1 吾爱币 +81 热心值 +48 收起 理由
95827 + 1 + 1 用心讨论,共获提升!
dandanquanyi + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
ziiyao + 1 + 1 用心讨论,共获提升!
xxx2017 + 1 + 1 wenq的现在一页的图片被切割为6片,获取的分析或方法
QWQ2333 + 1 + 1 虽然看不懂 但是感觉很牛逼
axin2129 + 1 我很赞同!
无聊网络 + 1 + 1 我很赞同!
夏目友人赖账 + 1 谢谢@Thanks!
二十瞬 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
2272161 + 1 + 1 谢谢@Thanks!
MudMir + 1 + 1 我很赞同!
aabbcc123123 + 1 + 1 用心讨论,共获提升!
pdcba + 1 + 1 谢谢@Thanks!
常胜将军 + 1 + 1 我很赞同!
tonyiyong + 1 + 1 用心讨论,共获提升!
一家之言 + 1 + 1 谢谢@Thanks!
xiexuhuai + 1 + 1 用心讨论,共获提升!
timeni + 1 + 1 用心讨论,共获提升!
kelvar + 1 + 1 谢谢@Thanks!
Courser + 1 + 1 谢谢@Thanks!
1MajorTom1 + 1 我很赞同!
2286624681 + 1 + 1 用心讨论,共获提升!
wmsuper + 3 + 1 谢谢@Thanks!
Hqbhbw + 1 + 1 谢谢@Thanks!
DaiTian + 1 谢谢@Thanks!
nshark + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Azad + 3 + 1 膜拜大佬
chinawolf2000 + 1 + 1 热心回复!
Siestaaa + 1 + 1 谢谢@Thanks!
hxr + 1 + 1 我很赞同!
WLy0214 + 3 + 1 用心讨论,共获提升!
loooooooong + 1 + 1 用心讨论,共获提升!
yjn866y + 1 + 1 谢谢@Thanks!
ph1999 + 1 + 1 我很赞同!
loo1221ool + 1 + 1 我很赞同!
5omggx + 1 + 1 用心讨论,共获提升!
独行风云 + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
zhangmi008 + 1 + 1 我很赞同!
正己 + 4 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
血帆海盗DK + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
v.n.lee + 3 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
田田爱崽崽 + 1 + 1 汉字我都懂,但是组合到一起我居然读不懂.....
michiless + 1 + 1 热心回复!
逍遥枷锁 + 3 + 1 用心讨论,共获提升!
涛之雨 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
blindcat + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
long8586 + 1 + 1 谢谢@Thanks!
coder9527 + 1 + 1 热心回复!
漁滒 + 3 + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 我是不会改名的 发表于 2022-5-12 09:01
@无敌小儿
@poke2008
(4/6更新) 密码学工具 v1.12.3~~新版本全功能发布,按需配置~~
https://www.52pojie.cn/thread-1501153-1-1.html
(出处: 吾爱破解论坛)

免费评分

参与人数 1吾爱币 +1 收起 理由
ykrne + 1 有.NET版本吗??

查看全部评分

侃遍天下无二人 发表于 2023-5-20 07:43
本帖最后由 侃遍天下无二人 于 2023-5-20 11:54 编辑

其实如果只是想把资源搞下来的话,某学堂那个还真不需要费劲解密,可以这样
document.querySelector("#iFrame").contentDocument.documentElement.ownerDocument.querySelector("body")
然后把每个结果处理下单独保存到html文件中就行了,具体代码如下,这个可比下pdf简单多了
[JavaScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// ==UserScript==
// @name         文泉epub下载
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  下载文泉学堂的epub格式图书,将内容保存在一个压缩包中,后续可以用pandoc处理
// @author       kbtx
// @match        https://*.wqxuetang.com/deep/read/epub?bid=*
// @match        http://*.wqxuetang.com/deep/read/epub?bid=*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=wqxuetang.com
// @require https://cdn.bootcdn.net/ajax/libs/jszip/3.7.1/jszip.min.js
// @grant        none
// ==/UserScript==
 
(function() {
    'use strict';
 
    // Your code here...
    let button = document.createElement('button');
    button.textContent = '正在初始化...';
    // 设置按钮的样式
    button.style.position = 'fixed';
    button.style.bottom = '150px';
    button.style.right = '50px';
    document.body.appendChild(button);
    // 设置延迟,防止网页未加载导致的问题
    setTimeout( ()=>{
        let btn_prev = document.querySelector("#pagebox > div.read-content-btn-wrapper > a:nth-child(1)")
        let btn_next = document.querySelector("#pagebox > div.read-content-btn-wrapper > a:nth-child(2)")
        let btn_single_layout = document.querySelector("#app > div.page > div.read-header > div > div.read-header-left > div:nth-child(3) > div > div.popup-item.infeed-wrapper > div.popup-content-row > a:nth-child(1)")
        let current_page_count = 0;
        let zip = new JSZip();
        // 打包并下载zip
        function packZip(){
            zip.generateAsync({ type: 'blob' }).then(blob => {
                const link = document.createElement('a');
                link.href = URL.createObjectURL(blob);
                // 将文件命名为 "当前书名.zip"
                link.download = document.querySelector("#app > div.page > div.read-header > div > div.read-header-title").innerText + ".zip";
                link.click();
            });
        }
        button.textContent = '立即导出已有内容';
        button.addEventListener('click', packZip);
 
        let page_switcher = setInterval( ()=>{
            // 如果当前找不到翻页按钮,说明在双栏布局下,此时切换到单栏布局,并重新定位翻页按钮
            if(!btn_next || !btn_next.click){
                btn_single_layout.click();
                btn_prev = document.querySelector("#pagebox > div.read-content-btn-wrapper > a:nth-child(1)")
                btn_next = document.querySelector("#pagebox > div.read-content-btn-wrapper > a:nth-child(2)")
            }
            current_page_count++;
            if(btn_next.classList[0] === 'disabled'){
                // 已经到达最后一页,清理定时器
                clearInterval(page_switcher);
                packZip();
            }else{
                // 由于可能切换布局导致重新加载,这里要略微延迟一下,等待浏览器重新排版
                setTimeout( ()=>{
                    // 获取到的页面数据,格式为html
                    let page_data = document.querySelector("#iFrame").contentDocument.documentElement.ownerDocument.querySelector("body").innerHTML;
                    // 将data-src中的图片地址替换掉src的
                    page_data = page_data.replaceAll('data-src', 'data-sss')
                        .replaceAll(/src="([^"]*)"/g, '')
                        .replaceAll('data-sss', 'src');
                    // 将数据存入压缩包中
                    zip.file(current_page_count.toString().padStart(4, '0')+'.html', page_data)
                    // 先获取数据再翻页,可以确保所需数据已经加载
                    btn_next.click();
                },500);
            }
        }, 5000 )
        }, 5000 )
 
})();
bj9ye666 发表于 2022-5-12 00:53
头像被屏蔽
KatharsisKing 发表于 2022-5-12 01:26
提示: 作者被禁止或删除 内容自动屏蔽
taxuewuhen 发表于 2022-5-12 01:35
谢谢分享
aiyikegu 发表于 2022-5-12 07:48
感谢分享,辛苦了
zhjm21 发表于 2022-5-12 08:06
我是来学习的!谢楼主!
blindcat 发表于 2022-5-12 08:14
收藏,慢慢看,向大佬学习
penz 发表于 2022-5-12 08:25
认真学习
涛之雨 发表于 2022-5-12 08:29
小声逼逼,某东开发者这也太掉价了,用这种玩意加密。。。
不知道小偷会偷代码吗。。。

点评

垂死病中惊坐起,小偷竟是我自己  发表于 2022-5-12 09:09
note52019 发表于 2022-5-12 08:38
感谢分享,太详细了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-21 12:25

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表