精华内容
下载资源
问答
  • 初探js逆向

    万次阅读 2021-01-14 23:30:55
    转载自 三尾先生 博客 初探js逆向 在开始之前想先说下阅读完三尾先生这篇文章的一点个人理解,文章写得挺好的,很值得新手学习了解,首先谈下逆向破解思路 1.需要逆向的时候一般是遇到了加密问题,加密情况有参数...

    转载自 三尾先生 博客 初探js逆向

    在开始之前想先说下阅读完三尾先生这篇文章的一点个人理解,文章写得挺好的,很值得新手学习了解,首先谈下逆向破解思路
    1.需要逆向的时候一般是遇到了加密问题,加密情况有提交参数加密返回结果加密等情况。但不管怎样的加密只要页面能正常显示,那就有解密过程!
    2.先找到加密的字段名,通过字段名在sources全局搜索
    3.在含有这些字段的位置打断点,一般sources里看到的会是一行的压缩代码,我们可以通过点击左下角的双大括号格式化js代码 在这里插入图片描述
    4. 格式化代码后,通过断点一步步查看参数在哪一步骤发生了变化,或在哪一步骤获得的值。一般结果解密可按js执行顺序断点,这篇文章就是一篇典型的结果解密的文章。而请求参数的加密一般就需要反复断点了,先断点到加密完成(即ajax发送参数值)然后再反复断点一步一步的往上推直到原始参数的传参;

    (下面就是三尾先生 初探js逆向的原文了,很值得阅读了解练手)

    前言
    本文适合爬虫新手阅读,大佬也别绕道,欢迎指正和调教。

    js逆向是让爬虫萌新们比较头疼的一块领域,因为市面上大部分的爬虫书籍等教程都未涉及这方面知识,需要爬取用js加密的网站时常常无从下手,只能使用selenium等自动化框架来模拟人工点击。但这种方式往往效率低下,所以本文将以企名片这个网站为例,带大家初探js逆向。

    之所以选择这个网站,首先它难度不大,适合练手;其次即便破解了加密参数,想爬取数据还是得下些功夫,因为未登录情况下只显示一页数据,即便登录还得认证啥的比较麻烦。

    废话不多说,下面进入正题。

    环境准备
    (了解思路的朋友可忽略该环境准备,有个浏览器即可,这里推荐chrome)
    因为涉及js的调试验证,所以除了Python环境外,你还需要Nodejs(js的运行环境)和WebStorm(IDE)。

    Nodejs去官网下载安装包后直接一键安装即可,安装完毕后去控制台运行node --version,如果出现版本号即代表安装成功。

    WebStorm安装完后需要激活,激活教程网上很多,大家自行搜索。它是Jet Brains的产品(和PyCharm是同一家公司),所以使用方式与PyCharm很类似。

    分析过程
    直接访问这个地址https://www.qimingpian.com/finosda/project/pinvestment,看到的是这个界面:
    在这里插入图片描述
    我们需要获取图中红框里的数据,也就是创业项目列表。打开开发者工具,刷新一下页面,看看它发起了哪些请求:
    在这里插入图片描述
    为减少干扰,先只看XHR和Doc的请求,一共有三个:pinvestment、productListVip、industryFieldVip。

    在pinvestment的响应内容里,只能看到一堆js的调用,并没有我们想要的html,说明网页是由js动态生成的。

    而在productListVip和industryFieldVip的响应内容里,都有一个”encrypt_data”的参数,很明显这是一个加密参数,参数内容像是一串Base64字符。既然网站对这个参数做了加密,说明它不想被爬取,所以可以做个假设:我们的目标数据就是encrypt_data参数里的内容。

    有了这个假设,目的就很明确了,只要破解这个加密参数就行。

    爬虫新手们往往走完上面步骤就止步不前。不妨思考一下,参数虽做了加密,但网页毕竟要正常显示内容,所以在网页渲染的过程中,一定有个地方对这个参数做了解密,然后将数据写入html。

    也就是说,我们需要在网页渲染的过程里,一步步观察,看看到底是哪个位置对这个参数做了解密。

    在开发者工具里的Sources选项卡中,可以找到这个网页的js文件夹,界面右侧有断点调试栏。

    在这里插入图片描述
    在js文件里打上断点,然后一步步调试,就能重现网页渲染的过程。那么断点应该打在哪个位置呢?在断点调试栏里有个XHR/fetch Breakpoints,它支持在发送XHR请求的位置打上断点,我们找到的两个含加密参数的请求就是XHR类型的,正好用上这个功能。点击+号输入请求名称即可:
    在这里插入图片描述
    刷新页面,然后一步一步执行,发现可疑信息就把鼠标移上去看下
    在这里插入图片描述
    调试的两个小技巧:

    压缩的js点击左下角的花括号来美化
    在这里插入图片描述
    在调试过程中使用Console执行js代码。比如我觉得这个函数很可疑,想执行一下看看。

    在这里插入图片描述
    function o(t)就是我们需要的解密函数,可以看到它先调用s函数,传入了四个参数,除了a.a.decode(t)外其他三个都是写死的,最后用JSON.parse转为json对象。

    然而,找到解密函数后,我们要做的不是去分析它函数内部做了什么,虽然可以研究它的解密算法然后用Python重写,但这样太复杂且没必要。因为我们可以用PyExecJS这个库,直接用Python调用并执行js代码。

    这时候,WebStorm就派上用场了。新建一个js文件,把function o里涉及的代码全部抠下来。然后执行console.log把执行结果打印出来。篇幅问题就只贴部分代码:

    //解密函数
    function my_decrypt(t) {
        return JSON.parse(s("5e5062e82f15fe4ca9d24bc5", my_decode(t), 0, 0, "012345677890123", 1))
    }
    
    //解密函数依赖项
    function my_decode(t) {
        c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
        f = /[\t\n\f\r ]/g
        var e = (t = String(t).replace(f, "")).length;
        e % 4 == 0 && (e = (t = t.replace(/==?$/, "")).length),
        (e % 4 == 1 || /[^+a-zA-Z0-9/]/.test(t)) && l("Invalid character: the string to be decoded is not correctly encoded.");
        for (var n, r, i = 0, o = "", a = -1; ++a < e; )
            r = c.indexOf(t.charAt(a)),
                n = i % 4 ? 64 * n + r : r,
            i++ % 4 && (o += String.fromCharCode(255 & n >> (-2 * i & 6)));
        return o
    }
    
    //测试代码,加密参数太长就不贴上来了
    encrypt_data = "xxx"
    decrypt_data = my_decrypt(encrypt_data)
    console.log(decrypt_data)
    

    确实是我们需要的数据没错,最后用Python去调用解密函数就行了。调用时还有个需要注意的地方,因为直接返回object给Python会报错,所以这里将JSON.parse移除了,返回parse前的json字符串,

    //解密函数
    function my_decrypt(t) {
        return s("5e5062e82f15fe4ca9d24bc5", my_decode(t), 0, 0, "012345677890123", 1)
    }
    

    同时为了防止这串字符串内有特殊编码的字符,这里将它转成base64再return:

    function my_decrypt(t) {
        return new Buffer(s("5e5062e82f15fe4ca9d24bc5", my_decode(t), 0, 0, "012345677890123", 1)).toString("base64")
    }
    

    然后在Python中用base64库的b64decode方法来解码即可。

    本文所有代码已上传至Github,旨在学习和技术分享,请勿用于商业用途。

    总结
    最后总结一下,说说关于逆向的个人看法。

    之所以市面上很少有爬虫逆向的书籍,除了因为它比较”敏感”之外,也因为它并没有固定的方法论。上文提供的也只是一种思路,其实还是有很多取巧的方式,比如在我们已知参数名为encrypt_data的情况下,在js文件夹下全局搜索,分分钟就能找到解密函数。

    逆向过程挺糟心,也挺有趣的,且逆向成功后会有很大的成就感。

    总而言之,逆向是一个提出假设和实际验证的过程,比如上文中的encrypt_data,我们不能百分百确定它就是我们需要的数据,但可以假设它是,来作为我们的突破口,即便最后发现不是,大不了再做新的假设。这有点像侦探探案,通过已知的信息作为线索来抽丝剥茧,最终破案。

    展开全文
  • 初探js逆向(二)

    万次阅读 2021-01-14 23:48:01
    转载自 三尾先生 博客 初探js逆向(二) (时间问题还未实践,先搬后研究,感谢三尾先生的分享) 前言 如果你是没有任何 js 逆向经验的爬虫萌新,且没看过上篇的《初探js逆向》,建议先移步去看,因为本篇所使用的案例...

    转载自 三尾先生 博客 初探js逆向(二)
    (时间问题还未实践,先搬后研究,感谢三尾先生的分享)

    前言
    如果你是没有任何 js 逆向经验的爬虫萌新,且没看过上篇的《初探js逆向》,建议先移步去看,因为本篇所使用的案例相对上篇,难度会更大一些。

    在上一篇中,我们学习了一个入门案例的逆向流程。然而,加密的方式有很多,不可能以一概全。在进入本篇正题前,我们先回忆一下上篇的逆向思路:

    不妨思考一下,参数虽做了加密,但网页毕竟要正常显示内容,所以在网页渲染的过程中,一定有个地方对这个参数做了解密,然后将数据写入html。

    也就是说,我们需要在网页渲染的过程里,一步步观察,看看到底是哪个位置对这个参数做了解密。


    其实,这个思路有个前提:加密参数必须是请求返回的结果参数。如果网站在请求发起时就对请求参数做了加密,这个思路就不管用了。

    另外,在上篇中,因为案例比较简单,在找到解密函数之后工作就完成了 90%,所以抠代码的部分我们一笔带过。而本篇的案例,即便找到了加密位置,可能也只完成了一半工作。

    所以本篇将以七麦数据这个网站为例,介绍‘当请求参数被加密时的逆向思路’以及‘抠代码’的正确姿势。

    网站分析
    访问 https://www.qimai.cn/rank/marketRank/market/3/category/-2/date/2019-05-18 这个地址,可以看到:
    在这里插入图片描述
    红框中的App榜单列表即为我们的目标数据。来看看它发起了哪些请求:

    在这里插入图片描述
    在 marketRank 这个请求的响应内容里能够找到我们的目标数据,而且是清晰的 json 结构。但不要高兴得太早,我们再看一下它的请求参数:
    在这里插入图片描述
    market(3)、category(-2)、date 分别表示应用商店(应用宝)、类别(全部游戏)和日期,想构造它们都很简单,为了后文描述方便,我们暂且称之为‘简单三参’。

    需要重点关注的是这个 analysis,它是一个被加密的必选参数,请求时必须携带,否则无法正常返回数据。这时候你可能会想:“那我直接把它拷贝下来,模拟请求时再带上不就行了?”,然而,只要你稍微分析下就会发现,这个参数并不是固定的,它会随着简单三参的变化而改变。且这类榜单数据通常具有时效性,如果你想进行批量、持久地爬取有效数据,这种‘提前收集 analysis ’的方式是不现实的。

    说了这么多,好像有些偏离主题了,我们的目的不是爬取网站,而是学习 js 逆向。

    下面进入正题。
    逆向思路
    我们先用上篇中提到的方式,在xhr请求里打上断点,刷新一下网页。

    1558180850101

    代码执行到了 h.send(f),等等,好像哪里不对。send 不就是把请求发送出去吗?那是不是意味着请求参数在这步之前就已经生成完毕?观察一下上面几行代码,果然如此:

    在这里插入图片描述

    在 t 对象的 url 属性中可以看到,analysis 已经生成好了。那么我们再往下执行也没意义了,因为这个请求已经被发送到了服务端,客户端没必要再对它的参数进行解密。况且我们的目的是研究如何生成 analysis,而不是如何解密。

    那怎样才能找到生成 analysis 的位置呢?我们可以先把它的值记录下来,

    fGR5SX10dQ0oY3lVeGIkBH1HDQ1wExcWVlYPG1sAQltVRGJRXlMkFAxXBANUAQUHBQQFcBtV
    

    然后把断点打在一个比较早的地方(analysis 生成之前),一步步往下执行,这个值首次出现的位置,就是它生成的位置。

    想把断点打在 analysis 生成之前,可以在 Network 选项卡下,该请求的 Initiator 列里看到它的调用栈,调用顺序由上而下:
    在这里插入图片描述
    在前几条里随便选一个,点进去打上断点,这里我看get比较顺眼,就选了这条,并在默认位置打上断点。打上断点后别急着刷新网页,这里有个坑需要先避一下。因为除了marketRank之外,marketList这个请求也有一个 analysis 参数,它请求的是应用商店列表(百度、应用宝、360…)。为了避免干扰,我们不要刷新网页,而是切换类别:
    在这里插入图片描述
    通过这种方式来触发调试界面,就不会再去请求应用商店列表了。切换类别后即可触发弹出调试界面:

    在这里插入图片描述
    可以发现,简单三参都已经出现了,但还没发现 analysis,它应该还没生成,让我们继续往下执行。注意,执行过程中时刻关注是否出现类似(切换了类别,analysis肯定会变化,所以是类似)我们之前记录下来的那个值。

    此处省略一万步调试……,只要你耐心足够,就能找到下图中的代码:
    在这里插入图片描述
    可以看到,r 的值与我们之前记录的值很类似,为了进一步确定,可以在调试执行完成后看下请求中的 analysis 值是否与这个 r 的值一致。

    答案是一致的。也就是说,接下来只要把 r 的生成代码全部抠下来,我们就能生成 analysis 了。感觉也没那么难对吧?其实这个网站,抠代码才是重头戏。

    抠代码
    开头中提到,本案例即便找到了加密位置,也只完成了一半工作。因为加密函数中做了大量的代码混淆和迷惑眼球的函数调用,想把它完整抠下来也不是件容易的事。如果你没有强大的心脏和足够的耐心,请止步于此;但如果你就喜欢折腾,请接着往下看。

    鉴于本文的目的主要在于介绍‘请求参数被加密时的逆向思路’,所以不会对‘抠代码’的部分做详细讲解,也不会提供完整代码,但会稍微做一些提示,希望能对你有所帮助。以下提示内容只有真正去尝试抠代码的人才能看懂了。

    1. b 写死。

    2. 抠出 e 的生成函数,生成 e 。
      时间戳与difftime(写死好像不影响)

    3. 抠出 m 的生成函数,通过简单三参+URL 后缀+e 生成 m 。

      • 简单三参 sort 与 join
      • 忽略迷惑代码 ano[Ao]…
      • 进入 e 内部打断点
      • 只关注被调用并执行的代码
      • new一个Unit8Array
      • 找到写入Unit8Array的代码
      • 转base64
      • 封装f[La],便于步骤4调用
    4. 抠出 r 的生成函数,通过 m 和 b 生成 r。

      • 搞定步骤3之后心态千万不要崩,因为胜利就在眼前
      • 几个写死的变量
      • String[“fromCharCode”]

    贴张逆向成功的截图:
    在这里插入图片描述
    总结
    当请求的参数被加密时,将断点打在加密参数生成之前,在它的值首次出现的位置找到它的加密函数。

    抠代码时,如果代码做了大量混淆。需要辨别哪些代码是迷惑你的,哪些代码是真正起作用的,哪些代码是不需要抠的,哪些代码是可以自己用其他方式替代的。

    展开全文
  • js逆向

    2019-08-07 15:59:07
    做爬虫总是会遇到js的所以今天写一篇js逆向的文章,首先打开目标网址(http://ggzy.gzlps.gov.cn/jyxxgcgs/index_2.jhtml?tdsourcetag=s_pcqq_aiomsg) 首先我们打开网站就会发现进入详情页的链接是做了处理如下 这种...

    做爬虫总是会遇到js的所以今天写一篇js逆向的文章,首先打开目标网址(http://ggzy.gzlps.gov.cn/jyxxgcgs/index_2.jhtml?tdsourcetag=s_pcqq_aiomsg)
    首先我们打开网站就会发现进入详情页的链接是做了处理如下
    在这里插入图片描述在这里插入图片描述
    这种就是前端js做了处理,所以要分析出js是在哪里做处理的,下面是实现代码,复制代码可用
    import base64
    from Crypto.Cipher import AES
    def add_to_16(text):
    while len(text) % 16 != 0:
    text += ‘\0’
    return str.encode(text)

    def parseurl(url):
    text = url.split(’/’)[-1].split(’.’)[0]
    BS = AES.block_size
    pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
    key = ‘qnbyzzwmdgghmcnm’
    aes = AES.new(add_to_16(key), AES.MODE_ECB) # ECB模式
    encrypted_text = str(base64.encodebytes(aes.encrypt(add_to_16(pad(text)))), encoding=‘utf8’).replace(’\n’, ‘’)
    encrypted_text = encrypted_text[:-2].replace("/", “^”)
    url1 = ‘http://ggzy.gzlps.gov.cn/jyxxgcgs/%s.jhtml’ % encrypted_text
    return url1

    print(parseurl(“http://ggzy.gzlps.gov.cn:80/jyxxgcgs/22564.jhtml”))

    展开全文
  • 知乎登录js逆向及文章爬取js逆向 **在此声明:**本文章仅仅用于学习交流,不得用于商业活动。 登录支持账号密码登录及知乎移动端软件扫码登录。 文章爬取是把原文章的原样近似爬取,包括图片,链接,及评论。同时...

    知乎登录js逆向及文章爬取js逆向

    **在此声明:**本文章仅仅用于学习交流,不得用于商业活动。

    登录支持账号密码登录及知乎移动端软件扫码登录。

    文章爬取是把原文章的原样近似爬取,包括图片,链接,及评论。同时支持实时热点爬取。

    好久不更新文章了,现在不一样了,放假了。其实这个文章我好久之前就打算写,但是当时比较忙,就被搁置了,现在放假了,就继续来。要不就半途而废了。也浪费了以前的时间。废话不多说,我们直接开干。

    知乎,中文互联网高质量的问答社区和创作者聚集的原创内容平台,于 2011 年 1 月正式上线,以「让人们更好地分享知识、经验和见解,找到自己的解答」为品牌使命。知乎凭借认真、专业、友善的社区氛围、独特的产品机制以及结构化和易获得的优质内容,聚集了中文互联网科技、商业、影视等领域最具创造力的人群,已成为综合性、全品类、在诸多领域具有关键影响力的知识分享社区和创作者聚集的原创内容平台

    既然要模拟登陆知乎,那么我们就首先要知道登陆请求是发给谁的。

    image-20210202125655603
    在这里插入图片描述

    在知乎密码登录界面,打开开发者工具的Network,然后输入账号和错误的密码,我们可以看到它都发送了哪些请求。在Network中看到如下POST请求,headers中多了三个身份验证字段:x-xsrftokenx-ab-paramx-ab-pbx-zse-83经过测试,只有x-xsrftokenx-zse-83是必需的,并且x-xsrftoken是可以通过cookie获取的,x-zse-83是一个固定参数;而form data应该包括是加密后的信息,至少包括我们账号密码等信息。

    接下来是找form data加密方法及其需要参数。

    在这里就用老方法(适用于window系统)ctrl+shift+f,进行全局搜素,在这里我们就搜素一下sign_in,

    全局搜索结果打开搜索到的这个js文件,当然文件可能不止一个,我们一个一个打开,进行局部搜素(crtl+f),再次搜素sign_in如果有的话,点击左下角的{}进行格式化,之后会出现美化后的js代码,再找有我们需要的没。

    在寻找的过程中,会发现有一个是我们请求链接一下,如下图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GysXuO1s-1612276981000)(C:\Users\jyj34\Desktop\屏幕截图 2021-02-02 183626.jpg)]

    我们打一个断点再次登录

    这时会出现下面的情况:

    在这里插入图片描述

    在断点分析局部变量可以看出,这里的局部变量e包含了我们提交的用户名和密码。现在的任务还剩两个:

    • 凑齐这个表单中的其他变量,
    • 找到加密函数

    补全变量

    • clientIdgrantTypelangrefSourcesource 都是固定参数
    • captcha:验证码,这里因为没有触发验证码机制,为空。
    • usernamepassword:用户名和原始密码
    • timestamp:当前时间的时间戳,JavaScript中new Date().getTime()等价于Python中int(time.time()*1000)
    • signature:签名认证,一个加密参数。

    全局搜索signature,结果如下:
    在这里插入图片描述

    同时我们打一下断点,再次登录,会出现下面结果:

    在这里插入图片描述

    由上图可知signaturegrant_type + client_id + source + timestamp加密得到这么一段代码,看到SHA-1,知道signature它应该是用安全散列算法来进行加密的。有两种方法可以拿到signature:第一种使用python的hashlib库里的sha1模拟;第二种跳到js代码里找到逻辑代码然后使用python的execjs库执行js代码。因为python有这个算法,所以我们就用python进行模拟就好,

    代码:

        def signature(self):
            self.e["timestamp"] = str(self.timestamp())
            ha = hmac.new(b'd1b964811afb40118a12068ff74a12f4', digestmod=hashlib.sha1)
            grant_type = self.e['grant_type']
            client_id = self.e['client_id']
            source = self.e['source']
            timestamp = self.e["timestamp"]
            ha.update(bytes((grant_type + client_id + source + timestamp), 'utf-8'))
            self.e["signature"] = ha.hexdigest()
    

    可能看到有点困惑,怎么有self,因为这时从我sign类里直接粘贴过来了,到时看源码就知道了。

    其实我们还有一个要解决是验证码,最近知乎加入滑块,但是我发现有时候是验证码,有时候是文字点选,如果是滑块并不会在加密里发现关于滑块的踪迹,但能发现文字点选,英数验证码的踪迹,并且Ajian还发现在爬虫时你选择哪一种验证方式,到时验证在加密参数里加入哪一种就好了。或许是一个bug。在这里我选择的是英数验证码,来,我们看一下验证码请求(lang=en代表英数验证码)
    在这里插入图片描述

    可以看到它发送登录请求之前先去请求了验证码。先发送一个get请求看是否有验证码

    在这里插入图片描述

    这里如果为false就没有验证码。当这里为true的是时候,又发送一个put请求返回验证码的base64的格式

    在这里插入图片描述

    拿到这个字符串之后用python的base64库对它进行解码并保存为图片的格式,这样我们就拿到了验证码图片。拿到验证码之后我们还要发送一个post请求去验证验证码对不对

    在这里插入图片描述

    这些都解决了,下面就是form data的加密算法我们继续回到这张图:

    在这里插入图片描述

    decamelizeKeys就是form data加密函数

    在这里插入图片描述

    看上图,我们把鼠标放到红杠杠的地方,然后点击上面的红方框框。但是多次追寻无果,搞不清逻辑,这时我们换一种思路,以攻为进,这里全局搜索 encrypt;【encrypt:加密】,程序员对于加密函数一般是不会瞎写的,都会用这个encrypt进行表示。当然会有多个文件,我们一个一个打开,然后再美化一下下,再局部搜素,会发现下面这样的结果。

    在这里插入图片描述

    我们打一下断点,再次登录,会发现先登录下图:

    在这里插入图片描述

    然后是下图:

    在这里插入图片描述

    看来我们逻辑是没有错的,加密就是那里,接下来我们把js代码扣下来,经过我的整理,变成下面这样,当然,里面也有坑,但是之前搞js逆向时碰到过,没有的就百度,找高人,哈哈哈哈哈。

    form data加密代码:

    const jsdom = require("jsdom");
    const { JSDOM } = jsdom;
    const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
    window = dom.window;
    document = window.document;
    // function(module, exports, __webpack_require__) {
    //    "use strict";
    function t(e) {
        return (t = "function" == typeof Symbol && "symbol" == typeof Symbol.A ? function (e) {
                    return typeof e
                }
                : function (e) {
                    return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e
                }
        )(e)
    }
    
    Object.defineProperty(exports, "__esModule", {
        value: !0
    });
    var A = "2.0"
        , __g = {};
    
    function s() {
    }
    
    function i(e) {
        this.t = (2048 & e) >> 11,
            this.s = (1536 & e) >> 9,
            this.i = 511 & e,
            this.h = 511 & e
    }
    
    function h(e) {
        this.s = (3072 & e) >> 10,
            this.h = 1023 & e
    }
    
    function a(e) {
        this.a = (3072 & e) >> 10,
            this.c = (768 & e) >> 8,
            this.n = (192 & e) >> 6,
            this.t = 63 & e
    }
    
    function c(e) {
        this.s = e >> 10 & 3,
            this.i = 1023 & e
    }
    
    function n() {
    }
    
    function e(e) {
        this.a = (3072 & e) >> 10,
            this.c = (768 & e) >> 8,
            this.n = (192 & e) >> 6,
            this.t = 63 & e
    }
    
    function o(e) {
        this.h = (4095 & e) >> 2,
            this.t = 3 & e
    }
    
    function r(e) {
        this.s = e >> 10 & 3,
            this.i = e >> 2 & 255,
            this.t = 3 & e
    }
    
    s.prototype.e = function (e) {
        e.o = !1
    }
        ,
        i.prototype.e = function (e) {
            switch (this.t) {
                case 0:
                    e.r[this.s] = this.i;
                    break;
                case 1:
                    e.r[this.s] = e.k[this.h]
            }
        }
        ,
        h.prototype.e = function (e) {
            e.k[this.h] = e.r[this.s]
        }
        ,
        a.prototype.e = function (e) {
            switch (this.t) {
                case 0:
                    e.r[this.a] = e.r[this.c] + e.r[this.n];
                    break;
                case 1:
                    e.r[this.a] = e.r[this.c] - e.r[this.n];
                    break;
                case 2:
                    e.r[this.a] = e.r[this.c] * e.r[this.n];
                    break;
                case 3:
                    e.r[this.a] = e.r[this.c] / e.r[this.n];
                    break;
                case 4:
                    e.r[this.a] = e.r[this.c] % e.r[this.n];
                    break;
                case 5:
                    e.r[this.a] = e.r[this.c] == e.r[this.n];
                    break;
                case 6:
                    e.r[this.a] = e.r[this.c] >= e.r[this.n];
                    break;
                case 7:
                    e.r[this.a] = e.r[this.c] || e.r[this.n];
                    break;
                case 8:
                    e.r[this.a] = e.r[this.c] && e.r[this.n];
                    break;
                case 9:
                    e.r[this.a] = e.r[this.c] !== e.r[this.n];
                    break;
                case 10:
                    e.r[this.a] = t(e.r[this.c]);
                    break;
                case 11:
                    e.r[this.a] = e.r[this.c] in e.r[this.n];
                    break;
                case 12:
                    e.r[this.a] = e.r[this.c] > e.r[this.n];
                    break;
                case 13:
                    e.r[this.a] = -e.r[this.c];
                    break;
                case 14:
                    e.r[this.a] = e.r[this.c] < e.r[this.n];
                    break;
                case 15:
                    e.r[this.a] = e.r[this.c] & e.r[this.n];
                    break;
                case 16:
                    e.r[this.a] = e.r[this.c] ^ e.r[this.n];
                    break;
                case 17:
                    e.r[this.a] = e.r[this.c] << e.r[this.n];
                    break;
                case 18:
                    e.r[this.a] = e.r[this.c] >>> e.r[this.n];
                    break;
                case 19:
                    e.r[this.a] = e.r[this.c] | e.r[this.n];
                    break;
                case 20:
                    e.r[this.a] = !e.r[this.c]
            }
        }
        ,
        c.prototype.e = function (e) {
            e.Q.push(e.C),
                e.B.push(e.k),
                e.C = e.r[this.s],
                e.k = [];
            for (var t = 0; t < this.i; t++)
                e.k.unshift(e.f.pop());
            e.g.push(e.f),
                e.f = []
        }
        ,
        n.prototype.e = function (e) {
            e.C = e.Q.pop(),
                e.k = e.B.pop(),
                e.f = e.g.pop()
        }
        ,
        e.prototype.e = function (e) {
            switch (this.t) {
                case 0:
                    e.u = e.r[this.a] >= e.r[this.c];
                    break;
                case 1:
                    e.u = e.r[this.a] <= e.r[this.c];
                    break;
                case 2:
                    e.u = e.r[this.a] > e.r[this.c];
                    break;
                case 3:
                    e.u = e.r[this.a] < e.r[this.c];
                    break;
                case 4:
                    e.u = e.r[this.a] == e.r[this.c];
                    break;
                case 5:
                    e.u = e.r[this.a] != e.r[this.c];
                    break;
                case 6:
                    e.u = e.r[this.a];
                    break;
                case 7:
                    e.u = !e.r[this.a]
            }
        }
        ,
        o.prototype.e = function (e) {
            switch (this.t) {
                case 0:
                    e.C = this.h;
                    break;
                case 1:
                    e.u && (e.C = this.h);
                    break;
                case 2:
                    e.u || (e.C = this.h);
                    break;
                case 3:
                    e.C = this.h,
                        e.w = null
            }
            e.u = !1
        }
        ,
        r.prototype.e = function (e) {
            switch (this.t) {
                case 0:
                    for (var t = [], n = 0; n < this.i; n++)
                        t.unshift(e.f.pop());
                    e.r[3] = e.r[this.s](t[0], t[1]);
                    break;
                case 1:
                    for (var r = e.f.pop(), o = [], i = 0; i < this.i; i++)
                        o.unshift(e.f.pop());
                    e.r[3] = e.r[this.s][r](o[0], o[1]);
                    break;
                case 2:
                    for (var a = [], c = 0; c < this.i; c++)
                        a.unshift(e.f.pop());
                    e.r[3] = new e.r[this.s](a[0], a[1])
            }
        }
    ;
    var k = function (e) {
        for (var t = 66, n = [], r = 0; r < e.length; r++) {
            var o = 24 ^ e.charCodeAt(r) ^ t;
            n.push(String.fromCharCode(o)),
                t = o
        }
        return n.join("")
    };
    
    function Q(e) {
        this.t = (4095 & e) >> 10,
            this.s = (1023 & e) >> 8,
            this.i = 1023 & e,
            this.h = 63 & e
    }
    
    function C(e) {
        this.t = (4095 & e) >> 10,
            this.a = (1023 & e) >> 8,
            this.c = (255 & e) >> 6
    }
    
    function B(e) {
        this.s = (3072 & e) >> 10,
            this.h = 1023 & e
    }
    
    function f(e) {
        this.h = 4095 & e
    }
    
    function g(e) {
        this.s = (3072 & e) >> 10
    }
    
    function u(e) {
        this.h = 4095 & e
    }
    
    function w(e) {
        this.t = (3840 & e) >> 8,
            this.s = (192 & e) >> 6,
            this.i = 63 & e
    }
    
    function G() {
        this.r = [0, 0, 0, 0],
            this.C = 0,
            this.Q = [],
            this.k = [],
            this.B = [],
            this.f = [],
            this.g = [],
            this.u = !1,
            this.G = [],
            this.b = [],
            this.o = !1,
            this.w = null,
            this.U = null,
            this.F = [],
            this.R = 0,
            this.J = {
                0: s,
                1: i,
                2: h,
                3: a,
                4: c,
                5: n,
                6: e,
                7: o,
                8: r,
                9: Q,
                10: C,
                11: B,
                12: f,
                13: g,
                14: u,
                15: w
            }
    }
    
    Q.prototype.e = function (e) {
        switch (this.t) {
            case 0:
                e.f.push(e.r[this.s]);
                break;
            case 1:
                e.f.push(this.i);
                break;
            case 2:
                e.f.push(e.k[this.h]);
                break;
            case 3:
                e.f.push(k(e.b[this.h]))
        }
    }
        ,
        C.prototype.e = function (A) {
            switch (this.t) {
                case 0:
                    var t = A.f.pop();
                    A.r[this.a] = A.r[this.c][t];
                    break;
                case 1:
                    var s = A.f.pop()
                        , i = A.f.pop();
                    A.r[this.c][s] = i;
                    break;
                case 2:
                    var h = A.f.pop();
                    A.r[this.a] = eval(h)
            }
        }
        ,
        B.prototype.e = function (e) {
            e.r[this.s] = k(e.b[this.h])
        }
        ,
        f.prototype.e = function (e) {
            e.w = this.h
        }
        ,
        g.prototype.e = function (e) {
            throw e.r[this.s]
        }
        ,
        u.prototype.e = function (e) {
            var t = this
                , n = [0];
            e.k.forEach((function (e) {
                    n.push(e)
                }
            ));
            var r = function (r) {
                var o = new G;
                return o.k = n,
                    o.k[0] = r,
                    o.v(e.G, t.h, e.b, e.F),
                    o.r[3]
            };
            r.toString = function () {
                return "() { [native code] }"
            }
                ,
                e.r[3] = r
        }
        ,
        w.prototype.e = function (e) {
            switch (this.t) {
                case 0:
                    for (var t = {}, n = 0; n < this.i; n++) {
                        var r = e.f.pop();
                        t[e.f.pop()] = r
                    }
                    e.r[this.s] = t;
                    break;
                case 1:
                    for (var o = [], i = 0; i < this.i; i++)
                        o.unshift(e.f.pop());
                    e.r[this.s] = o
            }
        }
        ,
        G.prototype.D = function (e) {
            for (var t = window.atob(e), n = t.charCodeAt(0) << 8 | t.charCodeAt(1), r = [], o = 2; o < n + 2; o += 2)
                r.push(t.charCodeAt(o) << 8 | t.charCodeAt(o + 1));
            this.G = r;
            for (var i = [], a = n + 2; a < t.length;) {
                var c = t.charCodeAt(a) << 8 | t.charCodeAt(a + 1)
                    , s = t.slice(a + 2, a + 2 + c);
                i.push(s),
                    a += c + 2
            }
            this.b = i
        }
        ,
        G.prototype.v = function (e, t, n) {
            for (t = t || 0,
                     n = n || [],
                     this.C = t,
                     "string" == typeof e ? this.D(e) : (this.G = e,
                         this.b = n),
                     this.o = !0,
                     this.R = Date.now(); this.o;) {
                var r = this.G[this.C++];
                if ("number" != typeof r)
                    break;
                var o = Date.now();
                if (500 < o - this.R)
                    return;
                this.R = o;
                try {
                    this.e(r)
                } catch (e) {
                    this.U = e,
                    this.w && (this.C = this.w)
                }
            }
        }
        ,
        G.prototype.e = function (e) {
            var t = (61440 & e) >> 12;
            new this.J[t](e).e(this)
        }
        ,
    "undefined" != typeof window && (new G).v("AxjgB5MAnACoAJwBpAAAABAAIAKcAqgAMAq0AzRJZAZwUpwCqACQACACGAKcBKAAIAOcBagAIAQYAjAUGgKcBqFAuAc5hTSHZAZwqrAIGgA0QJEAJAAYAzAUGgOcCaFANRQ0R2QGcOKwChoANECRACQAsAuQABgDnAmgAJwMgAGcDYwFEAAzBmAGcSqwDhoANECRACQAGAKcD6AAGgKcEKFANEcYApwRoAAxB2AGcXKwEhoANECRACQAGAKcE6AAGgKcFKFANEdkBnGqsBUaADRAkQAkABgCnBagAGAGcdKwFxoANECRACQAGAKcGKAAYAZx+rAZGgA0QJEAJAAYA5waoABgBnIisBsaADRAkQAkABgCnBygABoCnB2hQDRHZAZyWrAeGgA0QJEAJAAYBJwfoAAwFGAGcoawIBoANECRACQAGAOQALAJkAAYBJwfgAlsBnK+sCEaADRAkQAkABgDkACwGpAAGAScH4AJbAZy9rAiGgA0QJEAJACwI5AAGAScH6AAkACcJKgAnCWgAJwmoACcJ4AFnA2MBRAAMw5gBnNasCgaADRAkQAkABgBEio0R5EAJAGwKSAFGACcKqAAEgM0RCQGGAYSATRFZAZzshgAtCs0QCQAGAYSAjRFZAZz1hgAtCw0QCQAEAAgB7AtIAgYAJwqoAASATRBJAkYCRIANEZkBnYqEAgaBxQBOYAoBxQEOYQ0giQKGAmQABgAnC6ABRgBGgo0UhD/MQ8zECALEAgaBxQBOYAoBxQEOYQ0gpEAJAoYARoKNFIQ/zEPkAAgChgLGgkUATmBkgAaAJwuhAUaCjdQFAg5kTSTJAsQCBoHFAE5gCgHFAQ5hDSCkQAkChgBGgo0UhD/MQ+QACAKGAsaCRQCOYGSABoAnC6EBRoKN1AUEDmRNJMkCxgFGgsUPzmPkgAaCJwvhAU0wCQFGAUaCxQGOZISPzZPkQAaCJwvhAU0wCQFGAUaCxQMOZISPzZPkQAaCJwvhAU0wCQFGAUaCxQSOZISPzZPkQAaCJwvhAU0wCQFGAkSAzRBJAlz/B4FUAAAAwUYIAAIBSITFQkTERwABi0GHxITAAAJLwMSGRsXHxMZAAk0Fw8HFh4NAwUABhU1EBceDwAENBcUEAAGNBkTGRcBAAFKAAkvHg4PKz4aEwIAAUsACDIVHB0QEQ4YAAsuAzs7AAoPKToKDgAHMx8SGQUvMQABSAALORoVGCQgERcCAxoACAU3ABEXAgMaAAsFGDcAERcCAxoUCgABSQAGOA8LGBsPAAYYLwsYGw8AAU4ABD8QHAUAAU8ABSkbCQ4BAAFMAAktCh8eDgMHCw8AAU0ADT4TGjQsGQMaFA0FHhkAFz4TGjQsGQMaFA0FHhk1NBkCHgUbGBEPAAFCABg9GgkjIAEmOgUHDQ8eFSU5DggJAwEcAwUAAUMAAUAAAUEADQEtFw0FBwtdWxQTGSAACBwrAxUPBR4ZAAkqGgUDAwMVEQ0ACC4DJD8eAx8RAAQ5GhUYAAFGAAAABjYRExELBAACWhgAAVoAQAg/PTw0NxcQPCQ5C3JZEBs9fkcnDRcUAXZia0Q4EhQgXHojMBY3MWVCNT0uDhMXcGQ7AUFPHigkQUwQFkhaAkEACjkTEQspNBMZPC0ABjkTEQsrLQ==");
    var b = function (e) {
        // console.log(__g._encrypt(encodeURIComponent(e)))
        return __g._encrypt(encodeURIComponent(e))
    }
    // exports.ENCRYPT_VERSION = A,
    // exports.default = b
    // e = "client_id=c3cef7c66a1843f8b3a9e6a1e3160e20&grant_type=password&timestamp=1611807648668&source=com.zhihu.web&signature=bf8a76bdc8f39b0f1083eb2529af5208ccfd4d5f&username=%2B8613213296461&password=fdjbcikjnverv&captcha=&lang=cn&utm_source=&ref_source=other_https%3A%2F%2Fwww.zhihu.com%2Fsignin%3Fnext%3D%252F"
    // console.log(b(e))
    

    下面就可以登录。但是我们仅仅就登录吗,不再搞点其它东西吗?所以我就搞一下实时热点,关注的人及其文章了,当然还有评论,文章图片呀。

    当然,我们如果仅仅想爬取它的热点是很简单的,不涉及什么js逆向,但是对于爬取关注了的人文章时,就不一样了,它就涉及了一下js代码,我们还得扣一扣,

    首先是怎么得到自己页面的主页,经过我的不懈努力,我还是发现一些蛛丝马迹,是一个叫url_token的东西,(我大概猜测是我们加入知乎的第一个名字),但是我们怎么获得呢?我发现当我们进入知乎首页时会加请求一个东西,当然在加载我的主业时,也会请求一个东西。那个东东是下面这个东西,如图所示(是不是听到这个话有点小小耳熟呀,嘿嘿嘿):

    在这里插入图片描述

    那个me?include=visits_count,就是我们要找的,其实一开始我也没在意它,但是看到它总是被请求,而且有个me,我就想是不是与我有关呢。然后我就点开看看,发现还真有,它是以json数据形式返回的。

    那我们的url_token解决了,下面就是怎么请求了,所以我们先看一下headers:

    在这里插入图片描述

    发现好的参数,并且有些是真长,不要怕,经过Ajian的测试,发现就x-zse-86x-zse-83是不可或缺的,那么接下来我们就全局搜索一下x-zse-86,会发现只要一个文件,(哎呦,太香了,哈哈哈哈)那我们直接打开吧,然后美化一下下,再进行局部搜索,但是局部搜索是会发现有两个,分别打断点试一试就好了,窝发现是下图那个

    在这里插入图片描述

    我们看一下它,我们能够明显看出,x-zse-86=2.0_+E,E是什么呢,往上看,E=y.signature,那我们看这个signature会怎么生成的,那我们局部搜索一下它吧,会发现下面的

    在这里插入图片描述

    原来signature就是一个函数,相当于对d进行了一些变换。猜想一下这里的(0,o.default)( (0,r.default)(d) )就是对明文d进行加密的函数,而d是由几个部分和“+”连接组成的,我们通过打断点的方式看看明文d是什么样子:
    在这里插入图片描述

    d=3_2.0``+``/api/v4/search_v3t=general&q=%E5%B1%B1%E4%B8%9C%E5%A4%A7%E5%AD%A6&correction=1&offset=0&limit=20&lc_idx=0&show_all_topics=0+``“AEAkV5lhDg-PTu36jNX6b3n62LBIfQP7QOk=|1551443146”,其实明文就是明文d是headers里的x-zse-83+url+cookie.d_c0

    这里我们可以通过在控制台中调用这个r.defauly方法,来看看它输出的是什么:

    在这里插入图片描述

    这个看着有点熟悉,有点像md5加密,我们不妨试一试,果然是,

    在这里插入图片描述

    结果与控制台输出一致,接下来我们应该找一下o.default这个函数了,但是找不到,那我我们再次试一试上面那个方法,找一找encrypt,不找不要紧,一找还真有,那我们打下断点试试,结果如下图所示:
    在这里插入图片描述

    那个e = "965c2f5d20c0ef9f1b50def3025bc261"是不是很像md5加密的东西,其实它就是,哈哈哈,接下来我们就可以扣js代码了。

    x-zse-86加密代码:

    ``

    const jsdom = require("jsdom");
    const {JSDOM} = jsdom;
    const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
    window = dom.window;
    document = window.document;
    XMLHttpRequest = window.XMLHttpRequest;
    
    var exports = {}
    
    function t(e) {
        return (t = "function" == typeof Symbol && "symbol" == typeof Symbol.A ? function (e) {
                    return typeof e
                }
                : function (e) {
                    return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e
                }
        )(e)
    }
    
    Object.defineProperty(exports, "__esModule", {
        value: !0
    });
    var A = "2.0"
        , __g = {};
    
    function s() {
    }
    
    function i(e) {
        this.t = (2048 & e) >> 11,
            this.s = (1536 & e) >> 9,
            this.i = 511 & e,
            this.h = 511 & e
    }
    
    function h(e) {
        this.s = (3072 & e) >> 10,
            this.h = 1023 & e
    }
    
    function a(e) {
        this.a = (3072 & e) >> 10,
            this.c = (768 & e) >> 8,
            this.n = (192 & e) >> 6,
            this.t = 63 & e
    }
    
    function c(e) {
        this.s = e >> 10 & 3,
            this.i = 1023 & e
    }
    
    function n() {
    }
    
    function e(e) {
        this.a = (3072 & e) >> 10,
            this.c = (768 & e) >> 8,
            this.n = (192 & e) >> 6,
            this.t = 63 & e
    }
    
    function o(e) {
        this.h = (4095 & e) >> 2,
            this.t = 3 & e
    }
    
    function r(e) {
        this.s = e >> 10 & 3,
            this.i = e >> 2 & 255,
            this.t = 3 & e
    }
    
    s.prototype.e = function (e) {
        e.o = !1
    }
        ,
        i.prototype.e = function (e) {
            switch (this.t) {
                case 0:
                    e.r[this.s] = this.i;
                    break;
                case 1:
                    e.r[this.s] = e.k[this.h]
            }
        }
        ,
        h.prototype.e = function (e) {
            e.k[this.h] = e.r[this.s]
        }
        ,
        a.prototype.e = function (e) {
            switch (this.t) {
                case 0:
                    e.r[this.a] = e.r[this.c] + e.r[this.n];
                    break;
                case 1:
                    e.r[this.a] = e.r[this.c] - e.r[this.n];
                    break;
                case 2:
                    e.r[this.a] = e.r[this.c] * e.r[this.n];
                    break;
                case 3:
                    e.r[this.a] = e.r[this.c] / e.r[this.n];
                    break;
                case 4:
                    e.r[this.a] = e.r[this.c] % e.r[this.n];
                    break;
                case 5:
                    e.r[this.a] = e.r[this.c] == e.r[this.n];
                    break;
                case 6:
                    e.r[this.a] = e.r[this.c] >= e.r[this.n];
                    break;
                case 7:
                    e.r[this.a] = e.r[this.c] || e.r[this.n];
                    break;
                case 8:
                    e.r[this.a] = e.r[this.c] && e.r[this.n];
                    break;
                case 9:
                    e.r[this.a] = e.r[this.c] !== e.r[this.n];
                    break;
                case 10:
                    e.r[this.a] = t(e.r[this.c]);
                    break;
                case 11:
                    e.r[this.a] = e.r[this.c] in e.r[this.n];
                    break;
                case 12:
                    e.r[this.a] = e.r[this.c] > e.r[this.n];
                    break;
                case 13:
                    e.r[this.a] = -e.r[this.c];
                    break;
                case 14:
                    e.r[this.a] = e.r[this.c] < e.r[this.n];
                    break;
                case 15:
                    e.r[this.a] = e.r[this.c] & e.r[this.n];
                    break;
                case 16:
                    e.r[this.a] = e.r[this.c] ^ e.r[this.n];
                    break;
                case 17:
                    e.r[this.a] = e.r[this.c] << e.r[this.n];
                    break;
                case 18:
                    e.r[this.a] = e.r[this.c] >>> e.r[this.n];
                    break;
                case 19:
                    e.r[this.a] = e.r[this.c] | e.r[this.n];
                    break;
                case 20:
                    e.r[this.a] = !e.r[this.c]
            }
        }
        ,
        c.prototype.e = function (e) {
            e.Q.push(e.C),
                e.B.push(e.k),
                e.C = e.r[this.s],
                e.k = [];
            for (var t = 0; t < this.i; t++)
                e.k.unshift(e.f.pop());
            e.g.push(e.f),
                e.f = []
        }
        ,
        n.prototype.e = function (e) {
            e.C = e.Q.pop(),
                e.k = e.B.pop(),
                e.f = e.g.pop()
        }
        ,
        e.prototype.e = function (e) {
            switch (this.t) {
                case 0:
                    e.u = e.r[this.a] >= e.r[this.c];
                    break;
                case 1:
                    e.u = e.r[this.a] <= e.r[this.c];
                    break;
                case 2:
                    e.u = e.r[this.a] > e.r[this.c];
                    break;
                case 3:
                    e.u = e.r[this.a] < e.r[this.c];
                    break;
                case 4:
                    e.u = e.r[this.a] == e.r[this.c];
                    break;
                case 5:
                    e.u = e.r[this.a] != e.r[this.c];
                    break;
                case 6:
                    e.u = e.r[this.a];
                    break;
                case 7:
                    e.u = !e.r[this.a]
            }
        }
        ,
        o.prototype.e = function (e) {
            switch (this.t) {
                case 0:
                    e.C = this.h;
                    break;
                case 1:
                    e.u && (e.C = this.h);
                    break;
                case 2:
                    e.u || (e.C = this.h);
                    break;
                case 3:
                    e.C = this.h,
                        e.w = null
            }
            e.u = !1
        }
        ,
        r.prototype.e = function (e) {
            switch (this.t) {
                case 0:
                    for (var t = [], n = 0; n < this.i; n++)
                        t.unshift(e.f.pop());
                    e.r[3] = e.r[this.s](t[0], t[1]);
                    break;
                case 1:
                    for (var r = e.f.pop(), o = [], i = 0; i < this.i; i++)
                        o.unshift(e.f.pop());
                    e.r[3] = e.r[this.s][r](o[0], o[1]);
                    break;
                case 2:
                    for (var a = [], c = 0; c < this.i; c++)
                        a.unshift(e.f.pop());
                    e.r[3] = new e.r[this.s](a[0], a[1])
            }
        }
    ;
    var k = function (e) {
        for (var t = 66, n = [], r = 0; r < e.length; r++) {
            var o = 24 ^ e.charCodeAt(r) ^ t;
            n.push(String.fromCharCode(o)),
                t = o
        }
        return n.join("")
    };
    
    function Q(e) {
        this.t = (4095 & e) >> 10,
            this.s = (1023 & e) >> 8,
            this.i = 1023 & e,
            this.h = 63 & e
    }
    
    function C(e) {
        this.t = (4095 & e) >> 10,
            this.a = (1023 & e) >> 8,
            this.c = (255 & e) >> 6
    }
    
    function B(e) {
        this.s = (3072 & e) >> 10,
            this.h = 1023 & e
    }
    
    function f(e) {
        this.h = 4095 & e
    }
    
    function g(e) {
        this.s = (3072 & e) >> 10
    }
    
    function u(e) {
        this.h = 4095 & e
    }
    
    function w(e) {
        this.t = (3840 & e) >> 8,
            this.s = (192 & e) >> 6,
            this.i = 63 & e
    }
    
    function G() {
        this.r = [0, 0, 0, 0],
            this.C = 0,
            this.Q = [],
            this.k = [],
            this.B = [],
            this.f = [],
            this.g = [],
            this.u = !1,
            this.G = [],
            this.b = [],
            this.o = !1,
            this.w = null,
            this.U = null,
            this.F = [],
            this.R = 0,
            this.J = {
                0: s,
                1: i,
                2: h,
                3: a,
                4: c,
                5: n,
                6: e,
                7: o,
                8: r,
                9: Q,
                10: C,
                11: B,
                12: f,
                13: g,
                14: u,
                15: w
            }
    }
    
    Q.prototype.e = function (e) {
        switch (this.t) {
            case 0:
                e.f.push(e.r[this.s]);
                break;
            case 1:
                e.f.push(this.i);
                break;
            case 2:
                e.f.push(e.k[this.h]);
                break;
            case 3:
                e.f.push(k(e.b[this.h]))
        }
    }
        ,
        C.prototype.e = function (A) {
            switch (this.t) {
                case 0:
                    var t = A.f.pop();
                    A.r[this.a] = A.r[this.c][t];
                    break;
                case 1:
                    var s = A.f.pop()
                        , i = A.f.pop();
                    A.r[this.c][s] = i;
                    break;
                case 2:
                    var h = A.f.pop();
                    A.r[this.a] = eval(h)
            }
        }
        ,
        B.prototype.e = function (e) {
            e.r[this.s] = k(e.b[this.h])
        }
        ,
        f.prototype.e = function (e) {
            e.w = this.h
        }
        ,
        g.prototype.e = function (e) {
            throw e.r[this.s]
        }
        ,
        u.prototype.e = function (e) {
            var t = this
                , n = [0];
            e.k.forEach(function (e) {
                n.push(e)
            });
            var r = function (r) {
                var o = new G;
                return o.k = n,
                    o.k[0] = r,
                    o.v(e.G, t.h, e.b, e.F),
                    o.r[3]
            };
            r.toString = function () {
                return "() { [native code] }"
            }
                ,
                e.r[3] = r
        }
        ,
        w.prototype.e = function (e) {
            switch (this.t) {
                case 0:
                    for (var t = {}, n = 0; n < this.i; n++) {
                        var r = e.f.pop();
                        t[e.f.pop()] = r
                    }
                    e.r[this.s] = t;
                    break;
                case 1:
                    for (var o = [], i = 0; i < this.i; i++)
                        o.unshift(e.f.pop());
                    e.r[this.s] = o
            }
        }
        ,
        G.prototype.D = function (e) {
            console.log(window.atob(e));
            for (var t = window.atob(e), n = t.charCodeAt(0) << 8 | t.charCodeAt(1), r = [], o = 2; o < n + 2; o += 2)
                r.push(t.charCodeAt(o) << 8 | t.charCodeAt(o + 1));
            this.G = r;
            for (var i = [], a = n + 2; a < t.length;) {
                var c = t.charCodeAt(a) << 8 | t.charCodeAt(a + 1)
                    , s = t.slice(a + 2, a + 2 + c);
                i.push(s),
                    a += c + 2
            }
            this.b = i
        }
        ,
        G.prototype.v = function (e, t, n) {
            for (t = t || 0,
                     n = n || [],
                     this.C = t,
                     "string" == typeof e ? this.D(e) : (this.G = e,
                         this.b = n),
                     this.o = !0,
                     this.R = Date.now(); this.o;) {
                var r = this.G[this.C++];
                if ("number" != typeof r)
                    break;
                var o = Date.now();
                if (500 < o - this.R)
                    return;
                this.R = o;
                try {
                    this.e(r)
                } catch (e) {
                    this.U = e,
                    this.w && (this.C = this.w)
                }
            }
        }
        ,
        G.prototype.e = function (e) {
            var t = (61440 & e) >> 12;
            new this.J[t](e).e(this)
        }
        ,
        (new G).v("AxjgB5MAnACoAJwBpAAAABAAIAKcAqgAMAq0AzRJZAZwUpwCqACQACACGAKcBKAAIAOcBagAIAQYAjAUGgKcBqFAuAc5hTSHZAZwqrAIGgA0QJEAJAAYAzAUGgOcCaFANRQ0R2QGcOKwChoANECRACQAsAuQABgDnAmgAJwMgAGcDYwFEAAzBmAGcSqwDhoANECRACQAGAKcD6AAGgKcEKFANEcYApwRoAAxB2AGcXKwEhoANECRACQAGAKcE6AAGgKcFKFANEdkBnGqsBUaADRAkQAkABgCnBagAGAGcdKwFxoANECRACQAGAKcGKAAYAZx+rAZGgA0QJEAJAAYA5waoABgBnIisBsaADRAkQAkABgCnBygABoCnB2hQDRHZAZyWrAeGgA0QJEAJAAYBJwfoAAwFGAGcoawIBoANECRACQAGAOQALAJkAAYBJwfgAlsBnK+sCEaADRAkQAkABgDkACwGpAAGAScH4AJbAZy9rAiGgA0QJEAJACwI5AAGAScH6AAkACcJKgAnCWgAJwmoACcJ4AFnA2MBRAAMw5gBnNasCgaADRAkQAkABgBEio0R5EAJAGwKSAFGACcKqAAEgM0RCQGGAYSATRFZAZzshgAtCs0QCQAGAYSAjRFZAZz1hgAtCw0QCQAEAAgB7AtIAgYAJwqoAASATRBJAkYCRIANEZkBnYqEAgaBxQBOYAoBxQEOYQ0giQKGAmQABgAnC6ABRgBGgo0UhD/MQ8zECALEAgaBxQBOYAoBxQEOYQ0gpEAJAoYARoKNFIQ/zEPkAAgChgLGgkUATmBkgAaAJwuhAUaCjdQFAg5kTSTJAsQCBoHFAE5gCgHFAQ5hDSCkQAkChgBGgo0UhD/MQ+QACAKGAsaCRQCOYGSABoAnC6EBRoKN1AUEDmRNJMkCxgFGgsUPzmPkgAaCJwvhAU0wCQFGAUaCxQGOZISPzZPkQAaCJwvhAU0wCQFGAUaCxQMOZISPzZPkQAaCJwvhAU0wCQFGAUaCxQSOZISPzZPkQAaCJwvhAU0wCQFGAkSAzRBJAlz/B4FUAAAAwUYIAAIBSITFQkTERwABi0GHxITAAAJLwMSGRsXHxMZAAk0Fw8HFh4NAwUABhU1EBceDwAENBcUEAAGNBkTGRcBAAFKAAkvHg4PKz4aEwIAAUsACDIVHB0QEQ4YAAsuAzs7AAoPKToKDgAHMx8SGQUvMQABSAALORoVGCQgERcCAxoACAU3ABEXAgMaAAsFGDcAERcCAxoUCgABSQAGOA8LGBsPAAYYLwsYGw8AAU4ABD8QHAUAAU8ABSkbCQ4BAAFMAAktCh8eDgMHCw8AAU0ADT4TGjQsGQMaFA0FHhkAFz4TGjQsGQMaFA0FHhk1NBkCHgUbGBEPAAFCABg9GgkjIAEmOgUHDQ8eFSU5DggJAwEcAwUAAUMAAUAAAUEADQEtFw0FBwtdWxQTGSAACBwrAxUPBR4ZAAkqGgUDAwMVEQ0ACC4DJD8eAx8RAAQ5GhUYAAFGAAAABjYRExELBAACWhgAAVoAQAg/PTw0NxcQPCQ5C3JZEBs9fkcnDRcUAXZia0Q4EhQgXHojMBY3MWVCNT0uDhMXcGQ7AUFPHigkQUwQFkhaAkEACjkTEQspNBMZPC0ABjkTEQsrLQ==");
    
    function b(e) {
        console.log(e);
        console.log(encodeURIComponent(e));
        return __g._encrypt(encodeURIComponent(e))
    };
    

    我们的url_token可以获取到了,那么下面的许多都可以获取到了,其实x-zse-86我们破解后,当我吗爬取文章时也会用到,不过都是一样的加密参数,都需要x-zse-83+url+cookie.d_c0,我们最难的都解决了,还怕文章爬取吗,这里文章爬取我没有用xpath,用的是正则正则其实比xpath更适合,为什么呢?因为文章先以json返回,不管我是否看全文,都会在json里,当我们点击时,它就会被提取,渲染,然后就是我们看到的样子,同时我这次是把它们写在word里的。并且知乎大部分数据是以json形式返回。

    对了,那个扫码登录我是借鉴github上一个人的(链接:https://github.com/CharlesPikachu/DecryptLogin),我自己搞不成,也不想搞了,对于爬虫来说,我们等实现一种登录就好了,并不需要太多登录方式。越简单越好。

    好了,这个文章就到此结束了,如果想获取源码可以加我微信发送知乎源码,同时有什么不明白的可以和我交流。

    这是我的公众号可以点个关注:
    在这里插入图片描述

    在我公众号里可以加我微信。

    同时如果想了解互联网策略产品前世今生,可以关注下面这个公众号:

    在这里插入图片描述

    他在里面聊策略侃经济谈江湖思人生,满满的干货。

    我下期再见。

    展开全文
  • Js逆向分析

    2020-08-20 20:31:12
    1、js逆向分析一般过程? 2、Js逆向分析 确定网站的登录接口? 3、Js逆向分析 确定JS的位置? 4、Js逆向分析 观察js的执行过程? 5、Js逆向分析 执行js:观察代码中都需要那些参数? 6、Js逆向分析 的...
  • JS逆向学习

    2020-09-03 12:55:15
    JS逆向语法
  • 简单的Js逆向案例:在线百度翻译,写的还不错噢!!!
  • js逆向实战

    千次阅读 2020-05-04 15:22:50
    最近遇到了很多加密问题,需要做js逆向,app逆向。 就简单写一个破解成功的js逆向案例吧 就我个人而言,不太喜欢写爬虫相关的实战方法,毕竟灰色地带。 首先声明,本文仅做技术交流,请不要用于商业用途。 如有侵犯...
  • js逆向调试工具,集成常用js加密函数,前端js几种加密集合
  • 这是某资源论坛公布的不...2021年最新巫妖易语言+js逆向+安卓逆向hook培训教程(修复画质声音不同步不加密版),课程主要讲解的内容是易语言+js逆向+安卓逆向hook,课程是2020年11月底刚培训结束的,也是目前最新的课程
  • 在本篇内容里小编给大家整理的是关于js逆向解密之网络爬虫的相关知识点内容,需要的朋友们参考下。
  • JS逆向学习笔记

    2021-02-13 08:28:09
    JS逆向学习笔记 寻找深圳爬虫工作,微信:cjh-18888 文章目录 JS逆向学习笔记 一. JS Hook 1. JS HOOK 原理和作用 原理:替换原来的方法. (好像写了句废话) 作用: 可以去Hook一些内置的...
  • 爬虫之简单js逆向

    万次阅读 2019-10-14 11:49:54
    本次js逆向没有存在代码混淆,所以还是比较简单的,重要的就是js逆向的思路,目标网站https://notice.qb.com/detail?noticeId=215让我们开始吧 进入网站后按F12,查看DOC中的,可以看出该网页一部分内容是异步加载...
  • 2021年最新巫妖易语言+js逆向+安卓逆向hook培训教程(修复画质声音不同步不加密版),课程主要讲解的内容是易语言+js逆向+安卓逆向hook,课程是2020年11月底刚培训结束的,也是目前最新的课程。 学习地址 百度:...
  • 2021年最新巫妖易语言-js逆向-安卓逆向hook教程-10.12上课录像(这课不用看,属于闲聊) 2021年最新巫妖易语言-js逆向-安卓逆向hook教程-10.13上课录像 2021年最新巫妖易语言-js逆向-安卓逆向hook教程-10.14上课录像 ...
  • js逆向微博案例

    2019-12-19 10:27:00
    js逆向 js逆向就是从网页的js找到加密的参数,实现破解加密,拿到cookie 微博登录案例 手动操作流程 访问首页https://weibo.com 输入用户名和密码 点击登录 如果有验证码,就输入验证码验证 成功跳转到微博首页面 ...
  • 网易云音乐JS逆向

    千次阅读 2021-02-01 23:08:14
    网易云音乐之JS逆向 1. 文章目录 2. 页面分析 当我们用chrome浏览器 (推荐用谷歌) 进入网易云官网,找到一首你喜欢的歌。 打开 f12 功能, 点击 XHR 过滤, 这个时候,我们点击播放, 在右侧就会重新捕获到新的网络...
  • python有道翻译js逆向

    2021-01-09 18:28:58
    文章目录前言一、JS逆向是什么?二、分析和编写代码1.分析2.编写代码总结 前言 js逆向第一战。 一、JS逆向是什么? 抓取网页端数据时,经常被加密参数、加密数据所困扰,获取不到想要的数据。这个时候需要根据...
  • JS逆向学习笔记 - 持续更新中

    千次阅读 多人点赞 2020-11-11 00:46:53
    JS逆向学习笔记 文章目录JS逆向学习笔记一. JS Hook1. JS HOOK 原理和作用原理:替换原来的方法. (好像写了句废话)作用: 可以去Hook一些内置的函数, 例如Debugger, setInterval,JSON.stringify等等2.JSHook 检测与...
  • JS逆向steam登录

    2021-04-22 10:43:40
    JS逆向steam登录 前言: 我们爬虫有时候,会遇到登录才能获取到数据的情况,最开始的时候我们只需要加入请求的data参数就可以,可是现在网站为了反爬,对登录的密码或者账号都做了加密处理,如果我们不破解出这些...
  • js逆向技巧分享

    2020-12-25 19:13:54
    js逆向技巧分享 当我们抓取网页端数据时,经常被加密参数、加密数据所困扰,如何快速定位这些加解密函数,尤为重要。本片文章是我逆向js时一些技巧的总结,如有遗漏,欢迎补充。 所需环境:Chrome浏览器 1. 搜索 ...
  • 漫画柜漫画下载js逆向分析 该爬虫仅用于研究和学习使用,这是一个简单的按照漫画链接来下载漫画的图片demo,后续可以根据自己的需求来做修改 一、页面分析(因为主要是写分析js所以只选了某一章) 1、目标网址:...
  • JS逆向索引目录

    2020-08-23 14:00:15
    很久没写文章了,准备写个js逆向合集。相关文章单独发表,这里只是一个索引目录。以下内容皆为一家之言,可能多有不妥以及不全的地方,欢迎加我微信共同学习交流。vx:zhangjingzheng6521 一·js与css基础 二·...
  • python-js逆向之js加密

    2020-04-20 16:45:56
    既然叫js加密,那么打开源代码看看,果然没有这些数字。 然后抱着试试心态,来个省时省力操作在左边搜索框搜索,哟吼.......... ...打开它在底部发现page,t,sign ...虽然才学js逆向一个月不到,那还是能分辨出...
  • js逆向要想是想,要非常熟悉web的运行流程,针对不同网站,有不同的思路,这个博客是针对人人直播的一个爬取,先直接上代码,然后在讲解,import requestsimport js2pyimport jsonheaders = {"User-Agent":"Mozilla/...
  • 2020年5月最新巫妖易语言-js逆向-安卓逆向hook教程-【2020.6.4】直播录像2020年5月最新巫妖易语言-js逆向-安卓逆向hook教程-【2020.6.5】直播录像2020年5月最新巫妖易语言-js逆向-安卓逆向hook教程-【5.15】上课须知...
  • python爬虫js逆向

    2019-09-22 11:10:36
    js逆向要想是想,要非常熟悉web的运行流程,针对不同网站,有不同的思路,这个博客是针对人人直播的一个爬取,先直接上代码,然后在讲解, import requests import js2py import json headers = { "User-Agent":...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,182
精华内容 872
关键字:

js逆向