精华内容
下载资源
问答
  • X-Shard倒是没什么问题,一看就是兴趣点的经纬度,但x-uab看过之后就让人心里苦了,js加密啊,只能去逆向解密了。 2 js逆向求解 最直接的思路是根据“x-uab”关键字在所有关键中查找(chrome浏览器-so
  • js逆向调试工具,集成常用js加密函数,前端js几种加密集合
  • JS逆向之新榜登录

    2021-01-20 01:56:36
    文章目录1. 模拟登录2. 解决 `password` 参数3. 解决`nonce`参数4. 解决`xyz`参数5. login 源码 1. 模拟登录 原创文章 401获赞 72访问量 3万+ 关注 私信 展开阅读全文 ...作者:保护我方豆豆
  • 主要介绍了Js逆向实现滑动验证码图片还原的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 知识点:1.js包为 recast 2.Recast除了parse/print/builder以外, 还有三项主要功能: run: 通过命令行读取js文件,并转化成ast以供处理。 tnt(recast.types.namedTypes): 通过assert()和check(),可以验证ast...
  • TiktokCrawler抖音爬虫(无/去掉水印),多线程爬虫+ JS逆向 项目普及技术:JS逆向(调用JS文件),抖音的一些接口加密,多线程操作,某些Linux命令操作(可在Win或Linux运行) 请在Python3下运行(版本太低可能会...
  • 阿里云资料ppt讲解介绍 来越的的公司注重数据,如何断绝他人独立网站数据是如今互联网公司的一个主题。js加密作为爬虫一个绕不过的关卡,如何更加有效率的破解加密参数,相信这节课会给你一个大概的思路。
  • 初探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逆向练习题100题

    2021-10-25 08:18:03
    练完这100题,随便找个月入1W工作不闹着玩?
  • 记录一些js逆向和爬虫以及其他,侵删 已包含以下内容: CrawlerLab爬虫攻防靶场 今日头条 大众点评 抖音 毛毛租房 漫画柜 烯牛数据 空中网 西瓜视频 优酷 掌上高考 猿人学爬虫攻防 验证码 麻瓜OCR 网易易盾 极验...
  • 我们团队目前已经出了两门课程,一门是系列课程适合新手,主要讲解常见的加密和 Js 逆向的基础和进阶知识,这是我们团队 10 位讲师共同打造,目前课程已经有近 1000 的学员,想想已经帮助近 1000 的爬虫工程师先...

    今天正好有些感想,所以水一篇文章分享一下。

    先从之前的文章的一些不足说起

    早期写过一些文章是我自学时侯的笔记,记着一些简单的加密,用的都是扣代码的方式,之后发现更好的方法直接导加密库就行,所以之后简单的加密代码都是直接导库的。

    比如:之前的文章有些时候是会提到一些扣代码的技巧,之后的文章就很少提及了,更多是直接点出网站用到的加密是那种算法,本意是想读者能直接用加密库就可以实现。

    而且早期的很多文章里的加密代码之前也讲过如何分析这是什么加密算法,有很多方法都带有很明显的加密算法的特征是可以通过搜索引擎解决掉的问题就直接跳了,想着像这类有加密库实现好的代码其实不值得花太多的时间去扣,知道是怎么回事就行了,所以文章是有一些跳跃性的,不适应的新手可以从近期的文章开始学习。

    我想早期我的文章里更多是补全了代码,导致一些读者朋友看到加密就想自己扣,不过个人认为不是错误的方向,不过i类似 MD5 AES RSA 这些加密动手补全过一次就好了,不要太过纠结,如果大家有心去扣代码可以多尝试分析一些网站自写的加密逻辑这样才能进步。

    应该学习哪些教程能够快速入门 Js 逆向?(有广告)

    第一、学习 Js 基础教程

    这里推荐菜鸟教程,之前推荐过 B 站上的 Js 教程,第一太多了很多人没耐心看完,第二就是不知道看到哪里才可以开始动手实践,每个人基础不同我也给不了建议,所以文字版的菜鸟教程可以实现随查随用,推荐!!

    https://www.runoob.com/js/js-tutorial.html

    第二、实践

    从简单的网站入手,自己走完分析的流程

    这里推荐公众号系列文章的前 10 篇,不够就再照着教程再搞 10 篇,这个时候请脱离公众号文章的限制,去自己找找平时因为加密劝退的网站,自己动手,遇到不会借助搜索引擎多学习,踩坑才能进步。

    第三、不会扣 Js 代码怎么办?

    个人认为这个更多是因为 Js 知识储备不够了(如果是检查环境不会补全的另说),对于新手多学学 Js, 了解下网站的加密上下文逻辑是什么,把这个逻辑的代码都复制出来粘贴到一起,再打印一下看看报错,把报错提示认真看一遍,提示少了什么再回到网页上找对应的代码复制过来

    如此反复,千万千万不要没有百度过就问为什么,大家时间都很宝贵,有这个时间多开车不好吗?

    第四、有系列教程推荐吗?

    作为夜幕的一员,我肯定首推自家的教程,课程是收费的,不适合想要白嫖的朋友。

    我们团队目前已经出了两门课程,一门是系列课程适合新手,主要讲解常见的加密和 Js 逆向的基础和进阶知识,这是我们团队 10 位讲师共同打造,目前课程已经有近 1000 的学员,想想已经帮助近 1000 的爬虫工程师先一步学习爬虫进阶还是有点自豪。

    当然还是要简单说下课程的不足:我们的课程是完全使用自行搭建的练习平台搭配课程供学员学习的,不存在直接攻克某一个网站加密的教程,所以不适合想着能通过购买系列课程实现某个网站的快速逆向(想直接在这里氪金完成逆向)的朋友。

    先看看目录内容能不能提供你要的知识再付费,不要盲目付费,无脑氪金。

    对所有的付费教程我都是建议大家好好思考前面这句话的

    第五、基础的都会,遇到难的就懵了,怎么办?

    多动手,多看看大佬们怎么做的,爬虫工程师就是与人斗其乐无穷的职位,网站一更新就完蛋了的情况比比皆是,所以多学点技能傍身吧,可以看看蔡老板,花哥等诸多大佬的公众号,或者夜幕爬虫论坛上大佬们的帖子学习学习,可以看到很多网站的解密思路,学习新知。

    推荐公众号:NightTeam、妄为写代码、菜鸟学Python编程

    论坛:https://bbs.nightteam.cn/

    第六、如何进阶 Js 逆向?

    u1s1,现在市场上的 Js 逆向大佬太多了,攻克某数、某验全家桶的能力集与一身,所以你认真看了上面的第四点你就知道如何进阶了,想进阶找夜幕啊。

    除了夜幕的进阶教程,肯定还有其他的路子,不过需要你有一定的评估能力,现在市场有不少的 Js 大佬都开通了付费文章,一杯饮料的钱就能解决困扰你很久的问题,所以适当付费也是可以的。

    除了上面之外就是多多请教大佬,不过姿势要摆正,大佬也是人也要恰饭的,没事给大佬的文章点个赞、点个好看、打个赏,如此混脸熟,我不信大佬会好意思不解答你的问题。

    正确提问的姿势才是最主要的啊。

    https://github.com/xianyucoder/Stop-Ask-Questions-The-Stupid-Ways

    继续送书

    刚刚接触咸鱼的朋友看完上面的两大段话估计已经开喷了,就知道钱钱钱,掉钱眼里了?

    emmmm,说的对,不过我不听,难道你不吃饭的?

    站直了挣钱还真不用不好意思,就像很多大佬不好意思说的,我今天要说。

    每个人的时间和精力都不是免费的,帮你是情分,不帮你是本分,见多了麻烦人家两三个小时连句谢谢都没有的情况,也见过抬手就是大佬牛逼,转身就骂的情况,所以你会选择怎么做呢?

    今天继续送两本书,感谢北京大学出版社的支持

    《Python 3.x网络爬虫从零基础到项目实战》介绍了如何使用Python来编写网络爬虫程序,内容包括网络爬虫简介、发送请求、提取数据、使用多个线程和进程进行并发抓取、抓取动态页面中的内容、与表单进行交互、处理页面中的验证码问题及使用Scrapy和分布式进行数据抓取,并在最后介绍了使用本书讲解的数据抓取技术对几个真实的网站进行抓取的实例,旨在帮助读者活学活用书中介绍的技术。

    本书提供了与图书内容全程同步的教学录像。此外,还赠送了大量相关学习资料,以便读者扩展学习。

    本书适合任何想学习Python爬虫的读者,无论您是否从事计算机相关专业,是否接触过Python,均可以通过学习本书快速掌握Python爬虫的开发方法和技巧。

    《Python人工智能开发从入门到精通》主要介绍了Python进行人工智能开发所需的技术、基础设施、核心理念、实施方法与流程,以及实战操作应用。

    全书共分3篇。1篇主要讲解了人工智能开发中常用Python编程语言相关入门知识,包括:1章 关于Python与开发环境配置、第2章 Python编程基础、第3章 Python编程进阶;第2篇主要讲解了人工智能开发相关知识的应用,包括:第4章 人工智能简介、第5章 机器学习理论基础、第6章 Python机器学习常用库的应用、第7章 第一个机器学习项目、第8章 典型的机器学习算法及应用实战、第9章 深度学习算法理论、第10章 深度学习之TensorFlow;第3篇通过3个综合案例,以神经网络在计算机视觉问题中的重要应用为线索,介绍深度学习人工智能技术在计算机视觉任务中的实践,包括:第11章 人工智能识万物、第3篇:第12章 人工智能知万物、第13章 人工智能绘万物。

    参与赠书

    以上就是今天的全部内容啦,咱们下次再会~

    Love&Share 

    [ 完 ]

    展开全文
  • JavaScript 逆向爬取实战

    千次阅读 多人点赞 2020-05-01 23:37:34
    “ 阅读本文大概需要 25分钟。 ”在上一节总结一些网站加密和混淆技术中,我们介绍了网页防护技术,包括接口加密和 JavaScript 压缩、加密和混淆。这就引出了一个问题,如果我们碰...

    阅读本文大概需要 25 分钟。

    在上一节总结一些网站加密和混淆技术中,我们介绍了网页防护技术,包括接口加密和 JavaScript 压缩、加密和混淆。这就引出了一个问题,如果我们碰到了这样的网站,那该怎么去分析和爬取呢?

    本节我们就通过一个案例来介绍一下这种网站的分析思路,本节介绍的这个案例网站不仅在 API 接口层有加密,而且前端 JavaScript 也带有压缩和混淆,其前端压缩打包工具是使用了现在流行的 Webpack,混淆工具是使用了 javascript-obfuscator,这二者结合结合起来,前端的代码会变得难以阅读和分析。

    如果我们不使用 Selenium 或 Pyppeteer 等工具来模拟浏览器的形式爬取的话,要想直接从接口层面上获取数据,基本上我们就要一点点调试分析 JavaScript 的调用逻辑、堆栈调用关系来整个弄清楚网站加密的实现方法了,我们可以称之为这个过程叫 JavaScript 逆向。这些接口的加密参数往往都是一些加密算法或编码的组合,完全搞明白其中的逻辑之后,我们就能把这个算法用 Python 模拟出来,从而实现接口的请求了。

    案例介绍

    案例的地址为:https://dynamic6.scrape.cuiqingcai.com/,页面如图所示。

    初看之下并没有什么特殊的,但仔细观察可以发现其 Ajax 请求接口和每部电影的 URL 都包含了加密参数。

    比如我们点击任意一部电影,观察一下 URL 的变化,如图所示。

    这里我们可以看到详情页的 URL 和包含了一个长字符串,看似是一个 Base64 编码的内容。

    那么接下来直接看看 Ajax 的请求,我们从列表页的第 1 页到第 10 页依次点一下,观察一下 Ajax 请求是怎样的,如图所示。

    可以看到 Ajax 接口的 URL 里面多了一个 token,而且不同的页码这个 token 还是不一样的,这个 token 同样看似是一个 Base64 编码的字符串。

    另外更困难的是,这个接口还是有时效性的,如果我们把 Ajax 接口 URL 直接复制下来,短期内是可以访问的,但是过段时间之后就无法访问了,会直接返回 401 状态码。

    接下来我们再看下列表页的返回结果,比如我们打开第一个请求,看看第一部电影数据的返回结果,如图所示。

    这里我们把看似是第一部电影的返回结果全展开了,但是刚才我们观察到第一步电影的 URL 的链接却为 https://dynamic6.scrape.cuiqingcai.com/detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWIx,看起来是 Base64 编码,我们解码一下,结果为 ef34#teuq0btua#(-57w1q5o5--j@98xygimlyfxs*-!i-0-mb1,但是看起来似乎还是毫无规律,这个解码后的结果又是怎么来的呢?返回结果里面也并不包含这个字符串,那这又是怎么构造的呢?

    再然后,这仅仅是某一个详情页页面的 URL,其真实数据是通过 Ajax 加载的,那么 Ajax 请求又是怎样的呢,我们再观察下,如图所示。

    好,这里我们发现其 A jax 接口除了包含刚才所说的 URL 中携带的字符串,又多了一个 token,同样也是类似 Base64 编码的内容。

    那么总结下来这个网站就有如下特点:

    •列表页的 Ajax 接口参数带有加密的 token•详情页的 URL 带有加密 id•详情页的 Ajax 接口参数带有加密 id 和加密 token

    那如果我们要想通过接口的形式来爬取,必须要把这些加密 id 和 token 构造出来才行,而且必须要一步步来,首先我们要构造出列表页 Ajax 接口的 token 参数,然后才能获取每部电影的数据信息,然后根据数据信息构造出加密 id 和 token。

    OK,那到现在为止我们就知道了这个网站接口的加密情况了,我们下一步就是去找这个加密实现逻辑了。

    由于是网页,所以其加密逻辑一定藏在前端代码里面,但上节课我们也说了,前端为了保护其接口加密逻辑不被轻易分析出来,会采取压缩、混淆的一些方式来加大分析的难度。

    好,那么我们 就来看看这个网站的源代码和 JavaScript 文件是怎样的吧。

    首先看看网站源代码,我们在网站上点击右键,弹出选项菜单,然后点击「查看源代码」,可以看到结果如图所示。

    内容如下:

    <!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title>Scrape | Movie</title><link href=/css/chunk-19c920f8.2a6496e0.css rel=prefetch><link href=/css/chunk-2f73b8f3.5b462e16.css rel=prefetch><link href=/js/chunk-19c920f8.c3a1129d.js rel=prefetch><link href=/js/chunk-2f73b8f3.8f2fc3cd.js rel=prefetch><link href=/js/chunk-4dec7ef0.e4c2b130.js rel=prefetch><link href=/css/app.ea9d802a.css rel=preload as=style><link href=/js/app.5ef0d454.js rel=preload as=script><link href=/js/chunk-vendors.77daf991.js rel=preload as=script><link href=/css/app.ea9d802a.css rel=stylesheet></head><body><noscript><strong>We're sorry but portal doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.77daf991.js></script><script src=/js/app.5ef0d454.js></script></body></html>
    

    这是一个典型的 SPA (单页 Web 应用)的页面, 其 JavaScript 文件名带有编码字符、chunk、vendors 等关键字,整个这就是经过 Webpack 打包压缩后的源代码,目前主流的前端开发,如 Vue.js、React.js 的输出结果都是类似这样的结果。

    好,那么我们再看下其 JavaScript 代码是什么样子的,我们在开发者工具中打开 Sources 选项卡下的 Page 选项卡,然后打开 js 文件夹,这里我们就能看到 JavaScript 的源代码,如图所示。

    我们随便复制一些出来,看看是什么样子的,结果如下:

    (window['webpackJsonp']=window['webpackJsonp']||[])['push']([['chunk-19c920f8'],{'5a19':function(_0x3cb7c3,_0x5cb6ab,_0x5f5010){},'c6bf':function(_0x1846fe,_0x459c04,_0x1ff8e3){},'ca9c':function(_0x195201,_0xc41ead,_0x1b389c){'use strict';var _0x468b4e=_0x1b389c('5a19'),_0x232454=_0x1b389c['n'](_0x468b4e);_0x232454['a'];},'d504':...,[_0xd670a1['_v'](_0xd670a1['_s'](_0x2227b6)+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20')]);}),0x1),_0x4ef533('div',{'staticClass':'m-v-sm\x20info'},[_0x4ef533('span',[_0xd670a1['_v'](_0xd670a1['_s'](_0x1cc7eb['regions']['join']('、')))]),_0x4ef533('span',[_0xd670a1['_v']('\x20/\x20')]),_0x4ef533('span',[_0xd670a1['_v'](_0xd670a1['_s'](_0x1cc7eb['minute'])+'\x20分钟')])]),_0x4ef533('div',...,_0x4ef533('el-col',{'attrs':{'xs':0x5,'sm':0x5,'md':0x4}},[_0x4ef533('p',{'staticClass':'score\x20m-t-md\x20m-b-n-sm'},[_0xd670a1['_v'](_0xd670a1['_s'](_0x1cc7eb['score']['toFixed'](0x1)))]),_0x4ef533('p',[_0x4ef533('el-rate',{'attrs':{'value':_0x1cc7eb['score']/0x2,'disabled':'','max':0x5,'text-color':'#ff9900'}})],0x1)])],0x1)],0x1);}),0x1)],0x1),_0x4ef533('el-row',[_0x4ef533('el-col',{'attrs':{'span':0xa,'offset':0xb}},[_0x4ef533('div',{'staticClass':'pagination\x20m-v-lg'},[_0x4ef533('el-pagination',...:function(_0x347c29){_0xd670a1['page']=_0x347c29;},'update:current-page':function(_0x79754e){_0xd670a1['page']=_0x79754e;}}})],0x1)])],0x1)],0x1);},_0x357ebc=[],_0x18b11a=_0x1a3e60('7d92'),_0x4369=_0x1a3e60('3e22'),...;var _0x498df8=...['then'](function(_0x59d600){var _0x1249bc=_0x59d600['data'],_0x10e324=_0x1249bc['results'],_0x47d41b=_0x1249bc['count'];_0x531b38['loading']=!0x1,_0x531b38['movies']=_0x10e324,_0x531b38['total']=_0x47d41b;});}}},_0x28192a=_0x5f39bd,_0x5f5978=(_0x1a3e60('ca9c'),_0x1a3e60('eb45'),_0x1a3e60('2877')),_0x3fae81=Object(_0x5f5978['a'])(_0x28192a,_0x443d6e,_0x357ebc,!0x1,null,'724ecf3b',null);_0x6f764c['default']=_0x3fae81['exports'];},'eb45':function(_0x1d3c3c,_0x52e11c,_0x3f1276){'use strict';var _0x79046c=_0x3f1276('c6bf'),_0x219366=_0x3f1276['n'](_0x79046c);_0x219366['a'];}}]);
    

    嗯,就是这种感觉,可以看到一些变量都是一些十六进制字符串,而且代码全被压缩了。

    没错,我们就是要从这里面找出 token 和 id 的构造逻辑,看起来是不是很崩溃?

    要完全分析出整个网站的加密逻辑还是有一定的难度的,不过不用担心,我们本节会一步步地讲解逆向的思路、方法和技巧,如果你能跟着这个过程走完,相信还是能学会一定的 JavaScript 逆向技巧的。

    为了适当降低难度,本节的案例的 JavaScript 混淆其实并没有设置特别复杂,并没有开启字符串编码、控制流扁平化等混淆方式。

    列表页 Ajax 入口寻找

    好,那么接下来我们就开始第一步入口的寻找吧,这里就简单介绍两种寻找入口的方式:

    •全局搜索标志字符串•设置 Ajax 断点

    全局搜索标志字符串

    一些关键的字符串通常会作为找寻 JavaScript 混淆入口的依据,我们可以通过全局搜索的方式来查找,然后根据搜索到的结果大体观察是否是我们想找的入口。

    好,我们重新打开列表页的 Ajax 接口,看下请求的 Ajax 接口,如图所示。

    这里的 Ajax 接口的 URL 为 https://dynamic6.scrape.cuiqingcai.com/api/movie/?limit=10&offset=0&token=NTRhYWJhNzAyYTZiMTc0ZThkZTExNzBiNTMyMDJkN2UxZWYyMmNiZCwxNTg4MTc4NTYz,可以看到带有 offset、limit、token 三个参数,那关键就是找 token,我们就全局搜索下 token 是不是存在吧,我们可以点击开发者工具右上角的下拉选项卡,然后点击 Search,如图所示。

    这样我们就能进入到一个全局搜索模式,我们搜索 token,可以看到的确搜索到了几个结果,如图所示。 观察一下,下面的两个结果可能是我们想要的,我们点击进入第一个看下,定位到了一个 JavaScript 文件,如图所示。

    这时候可以看到整个代码都是压缩过后的,只有一行,不好看,我们可以点击左下角的 {} 按钮,美化一下 JavaScript 代码,如图所示。

    美化后的结果就是这样子了,如图所示。

    这时候可以看到这里弹出来了一个新的选项卡,其名称是 JavaScript 文件名加上了 :formatted,代表格式化后代码结果,在这里我们再次定位到 token 观察一下。

    那可以看到这里有 limit、offset、token 然后观察下其他的逻辑,基本上能够确定这就是构造 Ajax 请求的地方了,如果不是的话可以继续搜索其他的文件观察下。

    那现在,混淆的入口点我们就成功找到了,这是一个首选的找入口的方法。

    XHR 断点

    由于这里 token 这个字符串并没有被混淆,所以上面的这个方法是奏效的。之前我们也讲过,这种字符串由于非常容易成为找寻入口点的依据,所以这样的字符串也会被混淆成类似 Unicode、Base64、RC4 的一些编码形式,这样我们就没法轻松搜索到了。

    那如果遇到这种情况,我们可以怎么办呢?这里再介绍一种通过打 XHR 断点的方式来寻找入口。

    XHR 断点,顾名思义,就是在发起 XHR 的时候进入断点调试模式,JavaScript 会在发起 Ajax 请求的时候挺住,这时候我们可以通过当前的调用栈的逻辑顺着找到入口。

    怎么设置呢?我们可以在 Sources 选项卡的右侧,XHR/fetch Breakpoints 处添加一个断点选项。首先点击 + 号,然后这里就会让我们输入匹配的 URL 内容,由于 Ajax 接口的形式是 /api/movie/?limit=10... 这样的格式,所这里我们就截取一段填进去就好了,这里填的就是 /api/movie,如图所示。

    添加完毕之后重新刷新下页面,可以发现就进入了断点模式,如图所示。

    好,接下来我们重新点下 {} 格式化一下代码,看看断点是在哪里,如图所示。

    那这里看到有个 send 的字符,我们可以初步猜测这就是相当于发送 Ajax 请求的一瞬间。

    那到了这里感觉 Ajax 都马上要发出去了,是不是有点太晚了,我们想找的是构造 Ajax 的那个时候来分析 Ajax 参数啊?不用担心,这里我们通过调用栈就可以找回去。我们点击右侧的 Call Stack,这里记录了 JavaScript 的方法逐层调用过程,如图所示。

    这里当前指向的是一个名字为 anonymouns,也就是匿名的调用,在它的下方就显示了调用这个 anonymouns 的方法,名字叫做 _0x594ca1,然后再下一层就又显示了调用 _0x594a1 这个方法的方法,依次类推。

    这里我们可以逐个往下找下去,然后通过一些观察看看有没有 token 这样的信息,就能找到对应的位置了,最后我们就可以找到 onFetchData 这个方法里面实现了这个 token 的构造逻辑,这样我们也成功找到 token 的参数构造的位置了,如图所示。

    好,那到现在为止我们就通过两个方法找到入口点了。

    其实还有其他的寻找入口的方式,比如 Hook 关键函数的方式,稍后后文我们会讲到,这里就暂时不讲了。

    列表页加密逻辑寻找

    好,那么接下来我们已经找到 token 的位置了,可以观察一下这个 token 对应的变量叫做 _0xa70fc9,所以我们的关键就是要找这个变量是哪里来的了。

    怎么找呢?我们打个断点就好了。

    看下这个变量是在哪里生成的,我们在对应的行打一个断点,如果打了刚才的 XHR 断点的话可以先取消掉,如图所示。

    这时候我们就设置了一个新的断点了。由于只有一个断点,可以重新刷新下网页,这时候我们会发现网页停在了新的断点上面。

    那这里我们就可以观察下运行的一些变量了,比如我们把鼠标放在各个变量上面去,可以看到变量的一些值和类型,比如我们看 _0x18b11a 这个变量,会有一个浮窗显示,如图所示。

    另外我们还可以通过在右侧的 Watch 面板添加想要查看的变量名称,如这行代码的内容为:

    , _0xa70fc9 = Object(_0x18b11a['a'])(this['$store']['state']['url']['index']);
    

    我们比较感兴趣的可能就是 _0x18b11a 还有 this 里面额这个值了,我们可以展开 Watch 面板,然后点击 + 号,把想看的变量添加到 Watch 面板里面,如图所示。

    观察下可以发现 _0x18bba 这是一个 Object,它有个 a 属性,其值是一个 function,然后 this['$store']['state']['url']['index'] 的值其实就是 /api/movie,就是 Ajax 请求 URL 的 Path。_0xa70fc9 就是调用了前者这个 function 然后传入了 /api/movie 得到的。

    那么下面一步就是去寻找这个 function 在哪里了,我们可以把 Watch 面板的 _0x18bba 展开,这里会显示一个 FunctionLocation,就是这个 function 的代码位置,如图所示。

    点击进入之后发现其仍然是未格式化的代码,再次点击 {} 格式化一下代码。

    这时候我们就进入到了一个新的名字为 _0xc9e475 这个方法里面,这个方法里面应该就是 token 的生成逻辑了,我们再打上断点,然后执行面板右上角蓝色箭头状的 Resume 按钮,如图所示。

    这时候就发现我们就单步执行到这个位置了。

    接下来我们不断进行单步调试,观察一下这里面的执行逻辑和每一步调试过程中结果都有什么变化,如图所示。

    在每步的执行过程中,我们可以发现一些运行值会被打到代码的右侧并带有高亮表示,同时在 watch 面板还能看到每步的变量具体结果。

    最后我们总结出这个 token 的构造逻辑如下:

    •传入的 /api/movie 会构造一个初始化列表,变量命名为 _0x3dde76。•获取当前的时间戳,命名为 _0x4c50b4,push 到 _0x3dde76 这个变量里面。•将 _0x3dde76 变量用 , 拼接,然后进行 SHA1 编码,命名为 _0x46ba68。•将 _0x46ba68 (SHA1 编码的结果)和 _0x4c50b4 (时间戳)用逗号拼接,命名为 _0x495a44。•将 _0x495a44 进行 Base64 编码,命名为 _0x2a93f2,得到最后的 token。

    以上的一些逻辑经过反复的观察就可以比较轻松地总结出来了,其中有些变量可以实时查看,同时也可以自己输入到控制台上进行反复验证,相信总结出这个结果并不难。

    好,那现在加密逻辑我们就分析出来啦,基本的思路就是:

    •先将 /api/movie 放到一个列表里面•列表中加入当前时间戳•将列表内容用逗号拼接•将拼接的结果进行 SHA1 编码•将编码的结果和时间戳再次拼接•将拼接后的结果进行 Base64 编码

    验证下逻辑没问题的话,我们就可以用 Python 来实现出来啦。

    Python 实现列表页的爬取

    要 Python 实现这个逻辑,我们需要借助于两个库,一个是 hashlib,它提供了 sha1 方法;另外一个是 base64 库,它提供了 b64encode 方法对结果进行 Base64 编码。

    代码实现如下:

    import hashlib
    import time
    import base64
    from typing import List, Any
    import requests
    
    
    INDEX_URL = 'https://dynamic6.scrape.cuiqingcai.com/api/movie?limit={limit}&offset={offset}&token={token}'
    LIMIT = 10
    OFFSET = 0
    
    
    def get_token(args: List[Any]):
        timestamp = str(int(time.time()))
        args.append(timestamp)
        sign = hashlib.sha1(','.join(args).encode('utf-8')).hexdigest()
        return base64.b64encode(','.join([sign, timestamp]).encode('utf-8')).decode('utf-8')
    
    
    args = ['/api/movie']
    token = get_token(args=args)
    index_url = INDEX_URL.format(limit=LIMIT, offset=OFFSET, token=token)
    response = requests.get(index_url)
    print('response', response.json())
    

    这里我们就根据上面的逻辑把加密流程实现出来了,这里我们先模拟爬取了第一页的内容,最后运行一下就可以得到最终的输出结果了。

    另外,还有一些

    •Hook 原理•Hook 注入•Overrides 功能•Tampermonkey 插件•Python 模拟实现

    的内容,我放在了下一节,下一节会于 5.3 号发出,我们不见不散~

    崔庆才

    静觅博客博主,《Python3网络爬虫开发实战》作者

    隐形字

    个人公众号:进击的Coder

    长按识别二维码关注

    好文和朋友一起看~

    展开全文
  • JS 逆向涉及的语法全在这,拿走不谢!

    千次阅读 多人点赞 2020-08-09 15:27:29
    今天我们主要会介绍跟 Java Script 的逆向相关的基础知识以及 JavaScript 必备的语法以及一些进阶的内容。 目录 JavaScript 简介 1.1 JavaScript 介绍 1.2 网页三剑客 1.3 JavaScript 发展 JavaScript 语法 2.1...

    你好,我是悦创。

    欢迎关注公众号:AI悦创,最先更新在微信公众号!

    今天我们主要会介绍跟 Java Script 的逆向相关的基础知识以及 JavaScript 必备的语法以及一些进阶的内容。

    目录

    1. JavaScript 简介

      1.1 JavaScript 介绍

      1.2 网页三剑客

      1.3 JavaScript 发展

    2. JavaScript 语法

      2.1 数据类型

      ​ 2.1.1 Object 对象

      ​ 2.1.1.1 对象数据结构

      ​ 2.1.2 Array 数组

      ​ 2.1.3 String 字符串

      ​ 2.1.4 Number 数字

      ​ 2.1.5 Boolean 布尔值

      ​ 2.1.6 Map 映射

      ​ 2.1.7 Set 集合

      ​ 2.1.8 null/ undefined 空值/未定义 (2.1.9)

      2.2 控制流

      ​ 2.2.1 条件判断

      2.3 函数

      ​ 2.3.1 定义

      ​ 2.3.2 变量作用域

      ​ 2.3.3 高阶函数

      ​ 2.3.4 闭包

      ​ 2.3.5 特殊对象

    3. JavaScript 进阶

    4. 总结

    第一小节,我讲简单介绍一下 JavaScript 的背景,发展,以及它与 CSS HTML 之间的联系;

    第二小节,是本节课的重点,我将着重介绍 JavaScript 的语法知识,讲解其中的变量类型,函数以及控制流等等;

    第三小节,是本节课的进阶内容,我将介绍一些 JavaScript 的进阶知识,包括 事件循环、原型链、异步编程等等,这些进阶内容都是我们在处理 JS 逆向的时候可能遇到的基础知识,希望大家能静下心来学习。

    最后,我将把以上的知识点做一个总结。

    1. JavaScript 简介

    1.1 JavaScript 介绍

    众所周知,JavaScript 是一个弱类型语言,灵活并且强大是前端领域不可或缺的编程语言。在后端领域也有所作为,但是它是怎么来的呢?

    这里我简单介绍一下:JavaScript 最初由网景公司 netscape 的 Brendon Eich 发明,最初取名为 LiveScrip ,根据百度百科上的介绍,当年 34 岁的 Brendon Eich 只花了 10 天的时间,就将 JavaScript 发明了出来。但是由于缺乏严谨的论证和设计,导致后来编写出来的程序混乱不堪(其实也是因为多种版本的兴起,但 JavaScript 的出现解决了当初网页刷新需要很久的时间),JavaScript 在当时参考了 C 语言、Java 语言、Scheme 语言以及 Self 语言。因此,JavaScript 是函数式编程和面向对象编程的产物,相当于一个四不像。

    **然而,**就死这样的四不像,之后却成为风靡全球成为互联网中最受欢迎的语言之一。

    后来 JavaScript 与微软的 JScript 以及 CEnvi 的 ScriptEase 三足鼎立。1997 年的时候,在 ECMA (欧洲计算机制造商协会)的协调下,将几个版本的 JavaScript 统一成一个标准名为:ECMA-262,并发布 ECMAScript 1.0,简称 ES1。这为后面 JavaScript 的快速发展奠定了基础。

    1998 年和 1999 年分别发布了 ES2 和 ES3,10 年以后也就是 2009 年 ES5 才发布。ES5 中有很多现代的语法和数据结构是现代 JavaScript 基础,如今大多数 JS 的特性都是基于这个版本(ES5)。

    6 年后,也就是 2015年,ES6 发布,这个版本在 ES5 的基础上有长足的进步。有解决了回调地狱的 promise 等特性。因此,用达尔文的进化论来讲,经过了 20 多年的发展,JavaScript 已经从一个原始的大猩猩逐渐成长为一个心智完备且强大的现代人类。

    为了让同学们更加直观的了解到,我把它总结了下面几点:

    • JavaScript 诞生于 20多年前,由 NetScape 的 Brendan Eich 发明设计,最初命名为:LiveScript
    • 后来为了跟上当初比较火的 Java 就更名为了 JavaScript ,并与微软的 JScript 和 CEnvi 的 ScriptEase 三足鼎立
    • 1997 年,在 ECMA (欧洲计算机制造商协会)的协调下,由 NetScape、Sun、微软、Borland 组成的工作组确定统一标准:ECMA-262,并发布 ECMAScript 1.0,简称 ES1
    • 1998 年 ES2 发布,1999年 ES3 发布
    • 2009 年 ES5 发布,如今大多数 JS 的特性都是这个版本
    • 2015 年 ES6 发布,在 ES6 上有很多实用特性的改进

    1.2 网页三剑客

    都说 JavaScript 是前端语言,而我们知道前端有网页三剑客之称,这三剑客有哪些呢?

    • JavaScript
    • CSS
    • HTML

    那它们之间的关系如何呢?

    • HTML 是结构层,相当于人的骨骼和躯体

      例如:标题、段落、列表等等;

    • CSS 是表现,相当于人的衣服和装饰

      例如:字体、背景、颜色、边框、大小等等;

    • JavaScript 是行为层,相当于人的行为与动作

      例如:点击滚动条、事件与后端交互、小部件、点击弹出窗口、动态显示等等。

    1.3 JavaScript 发展

    名称内容
    前端React、Vue、Angular
    后端Node.js
    桌面端Electron
    物联网Arduino
    数据库MongoDB
    移动端React Native

    目前来看,JavaScript 因为其本身灵活以及容易上手的特性,再者涉及各个领域。

    1. 前端我就不说了,是 JavaScript 绝对的统治领域;

    2. 后端有 Node.js 是一个非常灵活的后端语言;

    3. 桌面端有 Electron ,大名鼎鼎的 VS Code 就是由 Electron 开发的;

    4. 物联网有 Arduino

    5. MongoDB 数据库Shell 也是用 JavaScript

    6. 在移动端 JavaScript 也在不断的发展,我们有 React Native 等优秀框架来简化移动端的开发流程。

    因此,我们可以看到 JavaScript 是非常全能的。我们有理由相信 JavaScript 在未来还会继续发展和流行,学习这样一门全能的语言是非常重要的(有帮助的)

    介绍完了 JavaScript 的背景和发展之后,我们来看一下这个课程的重点。

    2. JavaScript 语法

    JavaScript 语法,我将分成四个部分来讲。

    目录

    2.1 数据类型

    ​ 2.1.1 Object 对象

    ​ 2.1.1.1 对象数据结构

    ​ 2.1.2 Array 数组

    ​ 2.1.3 String 字符串

    ​ 2.1.4 Number 数字

    ​ 2.1.5 Boolean 布尔值

    ​ 2.1.6 Map 映射

    ​ 2.1.7 Set 集合

    ​ 2.1.8 null/ undefined 空值/未定义 (2.1.9)

    2.2 控制流

    ​ 2.2.1 条件判断

    2.3 函数

    ​ 2.3.1 定义

    ​ 2.3.2 变量作用域

    ​ 2.3.3 高阶函数

    ​ 2.3.4 闭包

    ​ 2.3.5 特殊对象

    2.4 特殊对象

    2.1 数据类型

    JavaScript 的数据类型有很多种,其中基本类型有六种,分别是以下类型:

    • 2.1.1 Object 对象

      ​ 2.1.1.1 对象数据结构

    • 2.1.2 Array 数组

    • 2.1.3 String 字符串

    • 2.1.4 Number 数字

    • 2.1.5 Boolean 布尔值

    • 2.1.6 Map 映射

    • 2.1.7 Set 集合

    • 2.1.8 null / undefined 空值/未定义(2.1.9)

    我将数组( Array )从对象(Object)中提取出来讲是因为它是一个非常重要的特殊对象,而映射 Map 以及集合 Set 是 ES6 中才出现的数据类型,我也将单独讲解一下。

    2.1.1 Object 对象

    • 是以 Key-Value 键值对的形式存在的集合
    • 键(Key)都是字符串(String)类型
    • 值(Value)可以是任意类型
    • 对象的拷贝分为深浅拷贝
      • 浅拷贝:只复制对象的内存地址,类似于指针
      • 深拷贝:完全克隆,生成一个新对象
    // define an object
    let obj = {hello: 'world'};
    
    // shallow copy
    let obj2 = obj;
    
    // deep copy
    let obj3 = JSON.parse(JSON.stringify(obj));
    

    我们先来看看对象,它是以键值对的形式存在的集合,**JavaScript 的对象跟 Python 中的数据类型——字典(Dictionary)非常类似。是一个用来表示映射的数据结构,但是它也有一些限制。**其中,一个比较大的限制是它的 Key 只能是字符串类型,而 Value 可以是任意的数据类型。

    另外,我们需要注意的一点是:

    JavaScript 中的深浅拷贝,这是 JavaScript 中对象或数组经常出现的操作,得加以区分。

    对于浅拷贝来说:新拷贝的变量储存的其实是被拷贝对象的内存地址,(相当于指针)任何在新拷贝的对象上的操作将直接改变被拷贝对象的内容。

    对于深拷贝来说:相反,新拷贝的变量是被拷贝对象的整体克隆,而不是内存地址。因此两者没有任何联系,分别改变其内容,也不会互相影响。

    • 对于一些引用操作,我们经常使用浅拷贝,这样操作比较方便
    • 而对于一些需要增删改的操作,例如:ToDoList 这样的应用来说,我们就需要深拷贝了。
    2.1.1.1 对象数据结构:
    // This is an Object
    let me = {
        name: 'AI悦创',
        gender: 'male',
        age: "secret",
        nationality: 'Chain',
        team: 'AIYC',
    };
    
    // assign attributes
    me.title = 'mr';
    me.education = 'College';
    
    // get all keys
    Object.keys(me)
    
    // get all Values
    Object.values(me)
    
    // iterate
    for (let key in me) {
        if (me.hasOwnProperty(key)){
            const value = me[key]
        }
    }
    

    上面的代码是对象的数据结构的一些基本操作,包括如何定义、获取值、设定值、遍历等等。

    2.1.2 Array 数组

    • 数组是一个有序排列的集合
    • 数组的值可以是任意类型
    • 数组的拷贝分为深浅拷贝
      • 与对象一致

    数组(Array)是一个有序排列的集合,与 Python 中列表(List)类似。数组的值可以是任意的数据类型,他同样有深浅拷贝的问题,这个跟我上面讲的对象是一致的,数组的增删改查都在下面列出来了。

    // This ia an array
    let items = [1, 2, 3, 4, 5];
    
    // get an item from the array
    let index = 1;
    items[index];
    
    // set an item value
    items[index] = 2;
    
    // get array length
    items.length;
    
    // append an item
    items.push(6);
    
    // insert an item
    items.splice(
        0, // index to insert
        0, // delete count
        0, // item to insert
    );
    
    // delete an item
    items.splice(
        0, // index to delete
        1, // delete count
    );
    
    // iterate
    items.map(d=>d);
    items.forEach(d=>{
        // do something
    })
    
    • 查找是利用索引来实现的,语法是: items 方括号加索引——items[index]

    • 要获取数组的长度,只要在其后面加 .length

    • 如果要在数组末尾添加一个元素,只需要调用 Push 这个方法;

    • 如果需要在某个地方插入一个元素,只需要调用 splice 这个方法;

    • 删除一个元素同样是用 splice 这个方法,但是需要注明第 2 个参数 —— Delete count 不为 0,所以这个 splice 这个方法既可以添加元素,又可以删除元素。大家不要混淆了!

    • 另外遍历数组的方法有两个:

      • 第一个方法是 Map
      • 第二个方法是 forEach

      上面两个方法的区别是,Map 是会返回一个新数组,而 forEach 不会。因此,在需要对数组元素进行操作并返回新数组的时候我们用——Map,如果不需要返回则用 forEach

    2.1.3 String 字符串

    • 字符串是任何 单引号或双引号 定义的类型
    // This is a string
    let str = 'Hello AI悦创';
    

    这个其实和许多语言类似,可是 JavaScript 不区分单引号和双引号;(如果,学过 Python 的就会知道其实和 Python 中的 字符串(str)数据类型很相似。)

    因此,JavaScript 规范上有些松散,我们用一些工具来对此进行规范,例如:ESLint。但代码的规范不在本专栏范围内,我就不多介绍了。

    # This is a string in Python
    str_data = 'AI悦创'
    

    2.1.4 Number 数字

    • 数字是任何表示数字的类型
    // This is a number
    let num = 123;
    

    可以是整数也可以是小数,注意:JavaScript 不像其他语言有整形和浮点型区别,所有数字相关的类型都是一个类型 Number。

    2.1.5 Boolean 布尔值

    • 布尔值是表示 TrueFalse 的类型
    // This is a Boolean
    let bool = true;
    

    映射(Map)和集合(Set)是 ES6 中新增的类型,以解决 ES5 中对象(Object)和数组(Array)的不足。

    2.1.6 Map 映射

    映射跟对象非常接近,不同的是:映射的键 (Key)可以是任何类型,其他跟对象类似。
    • 键(Key)值(Value)对关系的集合
    • 与对象不同的是,键可以为任何类型
    // This is a Map
    let m = new Map([
        [1, 'first as number'],
        ['1', 'first as strings']
    ]);
    
    // get a value from key
    m.get(1);
    
    // set a value
    m.set(1, 1);
    
    // clear all
    m.clear()
    

    2.1.7 Set 集合

    集合(Set)相当于去重后的数组
    • 相当于不重复值的数组

    映射(Map)和集合(Set)这两个数据类型用好了,其实是非常管用的——可以节省很多冗余(重复而冗杂)的代码。

    // This is a set
    let s = new Set([1, 2, 3]);
    

    2.1.8 null 空值

    • 相当于一个 ”空” 的值
    • 表示该值为空

    2.1.9 undefined 未定义

    • 表示 “未定义”
    • 通常用于比较不存在的属性或值

    注意:接下来要讲的是两个比较容易混淆的数据类型——空值(null)和未定义(undefined)

    null 表示一个值为空,不是其他任何类型;undefined 表示该变量没有定义——通常表示不存在的属性和值。这两个在概念上容易混淆,而在实际的应用中,我建议赋值的时候永远用 null ,而且在做比较的时候永远用三个等号而不是两个等号。

    Ps:

    三个等号与两个等号的区别: 由于 JavaScript 是弱类型语言,任何类型的值都可以做比较。三个等号为 true 的情况,要保证比较双方的值都相同而且类型相同。而两个等号比较会将数据类型转换成一个数据类型后再进行比较。

    因此,从开发程序的角度:三个等号的稳定性比两个等号的稳定性要强很多,我永远推荐 三个等号 ,而不是用两个等号。当然,在反爬的过程中有些开发者为了混淆对方,可能会采用两个等号的情况。这种情况大家要意识到,它们之间是有数据类型转换的。

    2.2 控制流

    循环

    • while
    • for
    • Array
      • map
      • forEach
    // This is a while for loop
    while (a < 10){
        a++;
    }
    
    // This is a for loop
    for (let i = 0; i < 10; i++){
        console.log(i);
    }
    
    // Array can also loop
    const arr = [1, 2, 3];
    
    // map loop
    const arr2 = arr.map(d => d + 1);
    
    // forEach loop
    arr.forEach(d => console.log(d));
    

    接下来我继续给你们介绍 JavaScript 控制流,这个还是比较容易理解的。首先,我们先来看一下循环,JavaScript 的循环,主要有三种:while 循环、for 循环、数组循环。

    • while 循环是跟其他语言类似的,都是在 while 后跟一个判断条件。
    • for 循环也类似,有三个条件参数
    • 数组循环分别是:map 和 forEach (这两个之前已经介绍过了)

    2.2.1 条件判断

    • 可以是 if () {} else {} 的形式
    • 也可以是 if () else 的形式
    • 中间条件用 else if 的形式
    // This is the best
    if (a > b) {
        // do something
    } else if (a == b) {
        // do something else
    } else {
        // do something more
    }
    
    // This is ok
    if (a > b) alert('ok');
    else alert('not ok');
    

    上面是 JavaScript 的条件判断,也就是 if else。非常简单跟其他的编程语言非常类似,这里就不多介绍了。大家注意其语法正确就可以。

    2.3 函数

    • 2.3.1 函数的定义
    • 2.3.2 变量作用域
    • 2.3.3 高阶函数
    • 2.3.4 闭包
    • 2.3.5 特殊对象

    JavaScript 的函数是本文的重点,因为在 JavaScript 逆向中,我们会看到很多跟函数相关的技巧和方法,请大家认真学习

    下面,我给大家介绍函数的定义、变量、作用域、高阶函数、闭包以及特殊对象,这些内容对我们理解 JavaScript 代码有着非常重要的作用。特别是高阶函数和闭包,在一些代码混淆里会有很多这样的例子。

    2.3.1 函数的定义

    • 带函数名
      • function funcName (param) {statement}
      • const funcName = function (param) {statement}
    • 不带函数名(匿名函数)
      • (function (param) {statement} () )
    // With function name 1
    function funcName1 (param) {
        // do something
        return param;
    };
    
    // With function name 2
    // const funcName 等于一个匿名函数
    const funcName2 = function (param) {
        // do something
        return param;
    };
    
    // Without function name
    (function (param) {
        // do something
        return param;
    })('Hello AI悦创')
    

    函数的定义有三种,前两种是带函数名定义的,而后一种是不带函数名定义的——也就是匿名函数。

    带函数名:

    第一种定义方式是 function 关键字加函数名称,然后定义参数和函数内容。

    第二种方式是用定义变量的方式,来定义函数。例如:const funcName 等于一个匿名函数。

    这两种定义是有区别的,第一种直接用 function 关键词的定义——是函数声明。而在 JavaScript 中函数声明高于一切,因此在浏览器加载好这段代码的时候,会首先将这个函数加载进来。因此,不管这个定义在哪个位置都可以被调用到。相反的是,用定义变量的方式的函数就会有一定的执行顺序。

    如果,用定义变量的方式的函数,在引用之后则会出现报错的情况,而函数声明则不会。

    匿名函数:

    最后是匿名函数,很多时候匿名函数在 JavaScript 逆向中 更为常见 ,因为这是一种有效的混淆方式。后面介绍的高阶函数和闭包都可能用到匿名函数。

    2.3.2 变量作用域

    • 变量的定义
      • var, const, let 定义的变量是有作用域的
      • var 定义的变量在各自的函数内部起作用
      • const、let 定义的变量为块级作用域
    • 变量的提升
      • 扫描整个函数体的语句,将所有声明变量提升到函数顶部
    • 全局作用域
      • 如果不指定 var,const,let 申明关键词来定义变量,该变量将被绑定到全局变量 windows 上
    • 块级作用域
      • let,const 将作用在 for、while 等循环语句里

    接下来我们来看一下变量的作用域,在 ES5 时代 JavaScript 变量定义主要是 var 这个关键词,后来在 ES6 中增加了 const、let 这种关键字。

    • 对于 var 来说,它的作用也是在函数内部,而 const、let 定义的变量的作用域是在块级作用域,待会我们会讲。

    • 所谓变量提升,就是 JavaScript 的引擎会扫描整个函数体的语句,将所有的声明变量提升到函数顶部。因此后来定义的变量被提前引用的话,是不会出翔 undefined 的错误。关于 JavaScript 变量提升的例子其实还有很多,具体大家可以上网找一下资料学习一下,加深自己的理解。

    • 全局作用域就是当不指定 var、const、let 等声明语句的时候,定义的变量会绑定在全局变量 Windows 上面。

    • 块级作用域就是指 const、let 定义的变量的作用域在 for、while 等循环语句中,而不能被外部访问到。这样的好处在于提升代码的封装性。

    2.3.3 高阶函数

    • 定义
      • 接收另一个函数作为参数的函数称作高阶函数
    • 用途
      • 回调
        • Callback
      • 数组操作
        • filter、sort、map、forEach
    function first(a, b, callback) {
        return callback(a, b);
    }
    
    function second(c, d) {
        return c + d;
    }
    
    first(1, 2, second);
    

    JavaScript 的函数中,另一个比较重要的知识点是高阶函数,所谓高阶函数就是:在函数中接收另一个函数作为参数,然后在函数中运行。

    那问题来了,为什么会有高阶函数的存在呢?

    在 ES6 的 Promise 出来之前,其中一个比较重要的作用就是异步操作,相信很多在 2015年前做过前端的朋友都会对回调函数不陌生,这是当时的一个异步编程的标准。但是这种随着 Promise、async/await 等方式的出现已经逐渐的被淘汰了。这个我们后面会将。

    另外比较重要的作用是在数组操作中,需要在方法中传入回调函数,来完成数组的操作。上面的代码是一个高阶函数的例子。主函数 first 接收一个回调函数作为参数传入,在主函数中获得 a,b 参数并传入回调函数 second 最后得到的结果作为返回值返回。

    如果,我们下面调用这个函数(first)得到的结果其实就是:1+2 = 3 的结果。

    2.3.4 闭包

    • 定义

      • 函数的返回值可以为函数
      • 所有的参数和变量都保存在返回函数中
      • 当调用返回函数时才会执行所有的运算逻辑(当返回的函数被执行的时候,才会将所有的运算逻辑返回结果)
    • 用途

      • 匿名自执行函数
      • 封装
      • 结果封装
    function closureFunc(a, b) {
        return function (i) {
            return Math.pow(a + b, i);
        }
    }
    

    闭包在 JavaScript 中同样是一个非常重要的概念,很多 JavaScript 逆向过程中都会碰到大量使用闭包的场景。

    其定义主要有三点,第一:函数的返回值为函数;第二,所有的参数和变量都保存在返回的函数里面;第三,当返回的函数被执行的时候,才会将所有的运算逻辑返回结果。(这个概念跟 Python 中的装饰器非常类似)有兴趣的同学将会在下一篇:Python 强大的装饰器

    如果你对装饰器比较熟悉的话,要理解闭包就非常简单了。这时候又小伙伴会问:闭包有什么作用呢?

    闭包有什么作用?

    其实闭包的作用有很多,这里我主要给大家列 3 点:匿名自执行函数、封装、结果缓存。

    • 第一匿名自执行函数:例如一段代码中定义一个返回函数的匿名函数,并调用这个函数。
    • 第二封装:封装闭包可以将一些计算逻辑隐藏在返回函数中,这样会提升代码的可读性
    • 第三结果缓存:很多时候我们并不急于将函数的结果计算出来,而是要留在后来(后面)执行。用闭包的方式可以将函数缓存在返回函数里,以供后面执行。很多前端的面试都会考闭包,其中最经典的就是**一个 for 循环加 setTimeOut 的场景。为什么最后总是输出一样的数字,**这个其实还跟事件循环有关,后面我会给大家讲到的。这道题的正确答案就是用闭包。

    好了,上面讲了这么多烧脑的概念,接下来我给大家介绍一个比较简单的知识点,也就是特殊对象。

    2.3.5 特殊对象

    • JSON
      • JSON、对象的序列化/反序列化的操作
      • JSON.stringfy 序列化
      • JSON.parse 反序列化
    • Date
      • JS 的时间操作对象
      • new Date(dateString)

    JS 中的特殊对象有不少,这里我就给大家介绍两个。第一个是 JSON 全部大写,这是一个静态变量,主要负责对象的序列化和反序列化。JSON.stringfy 负责序列化,JSON.parse 负责反序列化。

    你可能已经注意到,这两个操作在之前我们做对象的深拷贝中有用到,这其实只是其中的一种方式。另一种特殊对象是 Date,这个主要负责时间的处理,需要用 New 关键词来构造。

    3. JavaScript 进阶

    目录

    • 3.1 事件循环
    • 3.2 原型链
    • 3.3 异步编程
    • 3.4 浏览器存储
    • 3.5 跨域
    • 3.6 Webpack 打包

    3.1 事件循环(Event Loop)

    • 定义:主线程不断的重复获取执行消息、再获取执行不断循环的机制,被称为:事件循环
    • 为什么需要事件循环
      • JavaScript 是单线程的
      • 在处理异步操作的时候需要事件循环机制
    • 相关概念
      • 堆(Heap):大块非结构化内存区域,储存对象、数据
      • 栈(Stack):调用栈,储存该次循环,待主程序执行的任务
      • 队列(Queue):事件队列,先进先出被推入调用栈中
    • 宏任务(Macro Task)和微任务(Micro Task)
    • Node.js 事件循环

    很多人可能都听说过事件循环这个概念,但它究竟是个什么呢?

    其实要理解也不难,这里我们先看一下定义:事件循环是主线程不断的重复获取执行信息,再获取执行不断循环的机制。这里有些拗口,其实我们可以稍微理解一下。我们首先要知道,JavaScript 是单线程的,因此如果每一个异步操作都阻塞在主线程里,将会造成程序卡顿的现象,这样的结果是不可以接受的。因此我们需要一个事件循环机制,来处理这些异步操作。

    这里简单介绍三个相关概念:

    • 堆(Heap):这是大块的非结构化内存区域,用于储存对象和数据。
    • 栈(Stack):这里的栈其实是调用栈,用于储存该次循环所需要顺序执行的,待主程序任务执行的任务。
    • 队列(Queue):这是一个事件队列。采用先进先出的方式被推入调用栈。每一次循环结束后,主程序都会去任务队列里调用任务消息。任务消息与一个函数相关联,将其以及相关的同步函数推入调用栈里,主程序再将同步执行调用栈里面的函数。待执行完毕后进行下一轮循环,这就是 JavaScript 的事件循环。

    关于事件循环这里我们还有其他两个概念:宏任务和微任务,以及 Node.js 事件循环,鉴于文章篇幅的关系,我就不多介绍这两个知识点了,感兴趣的同学可以到网上搜索相关的资料,自学完成。

    3.2 原型链

    • 概念
      • prototype
      • __proto__
      • constructor
    • 应用场景
      • 继承、代码复用
    • ES6 出来后是否需要原型链?

    原型链是 JavaScript 中理解原型继承比较重要的概念,这里我们简单介绍一下,每一个函数都有一个原型 prototype 属性,这个属性指向函数的原型对象,每个 new 出来的对象都有一个 __proto__ 属性,指向对象的原型,每个原型都有一个 constructor 属性指向该关联的构造函数。

    当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性。如果还查不到,就会去找原型的原型,一直找到最顶层为止。

    原型链的用途主要是为了理解 JavaScript 代码当中继承和代码的复用的,因为在 ES6 出来之前,JavaScript 中只能用原型来进行对象的封装和继承,理解原型链有助于理解整个继承和调用的过程。但是 ES6 中出现了一个 class 关键字,相当于一个类的语法糖,可以直观的进行面向对象操作。

    因此,我们该不该理解原型链呢?

    我的答案是,需要理解。因为我们的专栏是 JavaScript 反爬虫(也就是 JavaScript 逆向),而很多需要阅读和操作的代码都需要经过 Babel 转译后的 ES5 的代码,其中就很可能包含原型链。因此,我们是有必要学习这个内容。我这里限于篇幅的关系不会详细讲解,请同学们看一下上面的图片例子以及网上的资料自行理解。

    3.3 异步编程

    • 回调函数 Callback

      • 通过传入回调函数作为参数在函数中异步执行
      • 优点:简单
      • 缺点:回调地狱
    • Promise

      • ES6 中出现的异步解决方案
      • 可以获取异步操作消息的对象
      • resolve / reject,then / catch
      • 优点:解决了回调地狱
      • 缺点:代码可读性不高

      前面我提到过回调函数,这里我详细讲解一下异步编程。在 ES6 的 promise 出来之前,我们只能用回调函数来解决异步执行问题。这样简单直观,但一个比较重大的问题是其可读性,也就是回调地狱,同学们可以看一下下面图片的回调地狱的例子,是不是非常的难以阅读。

    在 ES6 中的 promise 的出现,让回调地狱成为过去式,我们可以采用链式调用的方式来串行执行异步函数。promise 是一个可以获取异步操作信息的特殊对象,其中有 resolve + then 和 reject + catch 来分别处理成功和失败的回调,但它的缺点依然存在,在复杂情况下的异步操作可读性依然不高。

    为了解决 Promise 的问题,在 ES8 中出现了 async / await 这样的语法糖,帮助我们写出更加可读的代码。它是基于 Promise 的,因此需要了解 Promise 知识,async 相当于一个返回 Promise 的函数,await 可以在函数 async 函数中起阻塞的作用,这样可以大幅度提升代码的可读性。

    不过还有一个小小的缺点,并行异步操作还是需要用 promise.all 来执行。总的来说,我们推荐用 async / await 的方式来处理异步操作。

    在逆向过程中我们不会看到这个语法,但是我们需要了解其相关原理,这对我们或者逆向过程是有一些帮助的。

    ES6 Promise

    const makeRequests = () => {
        return callAPromise()
        	.then(() => callAPromise())
        	.then(() => callAPromise())
        	.then(() => callAPromise())
        	.then(() => callAPromise())
    }
    

    ES8 async / await

    async function fetchData() {
        const result1 = await callAp('https://example.com/endpoint1');
        const result2 = await callAp('https://example.com/endpoint2');
        // ...
    }
    

    3.4 浏览器存储

    • Cookies
      • 主要用于与服务端通信
      • 储存量小
    • Local Storage
      • 存储量相较于 Cookies 更大
      • 只能存储字符串
    • Session Storage
      • 只存在与当前 Session ,关闭浏览器就丢失了
      • 其他与 Local Storage 一样
    • IndexedDB
      • 相当于浏览器上的 SQL 数据库
      • 更大的储存空间
      • API 较难掌握
    FeatureCookiesLocal StorageSession StorageIndexedDB
    Storage Limit~4 KB~5 MB~5 MBUp to half of hard drive
    Persistent Data?YesYesNoYes
    Data Value TypeStringStringStringAny structured data
    Indexable?NoNoNoYes

    在爬虫过程中,有时候我们需要去获取浏览器储存的数据,下面我们来看看有哪些浏览器储存的方式。

    第一种是 Cookies,这是最简单的储存方式,主要用于跟服务器通信,因为每次请求都会带上 Cookies

    第二种是 Local Storage ,这个储存量相对大一些,但还是只能存储 字符串

    第三种是 Session Storage ,这个与 Local Storage 差不多,不同点是它随着 Session 的关闭就丢失了。

    第四种是 IndexedDB ,这个是存储量最大的方式,可以存储任何结构的数据,缺点是 API 相对来说比较麻烦,比较难以掌握。

    3.5 跨域

    • 定义:客户端与不同源的服务器通信

    这里说的 js 跨域是指通过 js 在不同的域之间进行数据传输或通信,比如用 ajax 向一个不同的域请求数据,或者通过 js 获取页面中不同域的框架中 (iframe) 的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。

    特别注意两点:

    1、如果是协议和端口造成的跨域问题“前台”是无能为力的;

    2、在跨域问题上,域仅仅是通过 “URL 的首部”来识别而不会去尝试判断相同的 ip 地址对应着两个域或两个域是否在同一个 ip 上。

    解决方法

    • CORS
      • 跨域资源共享,解决跨域请求的方案的成熟方案
    • JSONP
      • 基于 <script> 标签具有可跨域特性
      • 只能用于 GET 请求
    • iframe
      • 通过 <iframe> 标签在一个页面展示不同源的页面
      • 通过 PostMessage 进行页面之间的通信
    • 反向代理
      • 通过反向代理让客户端与服务端保持相同源

    相对于前面的知识点跨域并不是 JavaScript 逆向必须掌握的知识。但掌握了之后对你理解浏览器与服务器之间的数据交互会非常有帮助。我们来看一下几个常见的跨域方式。

    第一种 CORS 这是比较流行的跨域方案,叫跨域资源共享,是一个成熟的跨域解决方案,缺点是它有可能暴露端口,安全性方面有一定的风险。

    第二种 JSONP 这种比较老的跨域方式,是基于 <script> 标签可以跨域的方式,但这种方式只支持 get 请求,因此有很大的局限性。

    第三种 iframe 这是将不同源的网页,通过 <iframe> 标签放在同一个页面的跨域方式,页面之间用 PostMessage 来实现。

    第四种也就是最后一种也是比较安全的一种,就是利用反向代理,我们可以使用 Nginx 或者 IIS 对请求路由做反向代理。让静态资源与 API 是以同一个资源达到跨域的目的,这种方式隐藏了后面的端口,安全性比较高。

    3.6 Webpack 打包

    • 目的
      • 将不同类型的源文件编译打包成静态文件
    • 为什么使用 Webpack
      • 前端技术纷繁复杂,缺乏统一管理
      • 大型项目需要模块化
      • 对例如 JSX、TS 之类的新记数需要编译之后才能使用
    • 编译器
    • 插件
    • 优化

    Webpack 打包技术是前端技术野蛮生长的必然产物,它是将众多技术融合在一起的重要方式,Webpack 打包的目的是为了将不同格式的文件(例如:JS、TS、sass 等),打包编译成固定的静态文件。

    我们为什么要用 Webpack 呢?

    原因主要有三点:第一前端技术纷繁复杂,缺乏统一管理、第二大型项目需要模块化、第三对于像 JS、TS 这样的新技术,用编译之后才能使用。我们要用 Webpack 解决以上问题,此外 Webpack 需要配置特定的编译器,我们通常采用 babel作为 JavaScript 的编译器。Webpack 还提供很多插件来以次支持更多的特殊功能。

    最后 Webpack 有大量的配置,为了让打包过程变得高效和使用,我们还需要对这些配置进行优化,这也是个技术活。

    对 Webpack 打包有兴趣的同学可以到网上搜一下相关的知识,做进一步的学习。

    总结

    1. JavaScript 简介
    • 背景
    • 与 CSS / HTML 关系
    • 发展
    2. JavaScript 语法
    • 数据类型
    • 控制流
    • 函数
    • 特殊对象
    3. JavaScript 进阶
    • 事件循环
    • 原型链
    • 异步编程
    • 浏览器储存
    • 跨域
    • Webpack 打包

    我首先给 JavaScript 进行了一些背景和发展介绍,了解了它与 HTML、CSS 之间的关系,其次我们还了解到了相关语法,包括数据类型、控制流、函数以及特殊对象等等,最后我介绍了 JavaScript 进阶知识,帮助我们深入理解 JavaScript ,其中包括事件循环、原型链、异步编程、浏览器储存、跨域、Webpack 打包。经过本文的学习,相信同学们已经对 JavaScript 基础知识有一定的理解,希望接下来以后,你能在每个知识点上进一步学习,来以次巩固你的 JavaScript 知识,这对后面的实战课程都是有非常大的帮助。

    本次文章就这样结束了,我门下期再见!

    展开全文
  • 个人总结 - JS逆向解析

    万次阅读 多人点赞 2019-08-13 15:10:39
    }',62,6,'1|alert|if|javascript|showmsg|var'.split('|'),0,{})) 解决方法:将代码字符串放入javascript Eval官网解密 再看eval解密后的js文件尾部,有下面一个函数 function encryptString(str, e, m) { var key =...
  • 爬虫之简单js逆向

    万次阅读 2019-10-14 11:49:54
    本次js逆向没有存在代码混淆,所以还是比较简单的,重要的就是js逆向的思路,目标网站https://notice.qb.com/detail?noticeId=215让我们开始吧 进入网站后按F12,查看DOC中的,可以看出该网页一部分内容是异步加载...
  • Python爬虫进阶 JS 解密逆向实战 iBank登录 加速乐 cookie 破解 手机贝贝网登录 中国国航登录 中国空气质量参数加密破解 中国土地市场 中国电信登录 美团 token 破解 myToken 热搜榜破解 七麦数据 淘宝信用查询网 自...
  • 记录一下js逆向的网站 先写到这里吧~~~~ 下次再会(2020.08.25) 如果多人关注的话,会继续更新,且更新更频繁,你给的星星star就是我的动力,越多,更新越快! 综合类: ☆ ☆ ☆ ☆☆ ☆☆ ☆☆ ☆☆ ☆☆☆...
  • 浅谈_(js逆向)基础必备知识

    千次阅读 2021-01-10 02:08:10
    加粗样式随着技术的发展,js逆向成为爬虫必不可少的必备技术。我这里只是浅谈一下,根据自己的经验来说的。大蛇勿喷。 js逆向,你首先得懂函数吧 例子: . function per(x,y){ return x+y;} 比如这个函数 ...
  • JS逆向之豆瓣读书

    2021-09-04 19:54:43
    声明:本文仅限交流学习使用,请勿使用在任何非法商业活动,禁止用于非法用途。否则后果自负。如有侵权,请告知删除,谢谢! 测试结果
  • 首先要感谢各位对夜幕团队的信任和支持,在无数辣鸡培训机构和炒辣鸡课程套餐中选择了我们生产的辣鸡 ——《JavaScript 逆向系列课》。 课程内容问题 在报课之前,大家看过了课程目录,回顾一下: 序号 标签 ...
  • JavaScript 逆向爬取实战(下)

    千次阅读 2020-05-03 21:18:05
    “ 阅读本文大概需要 20分钟。 ”这一篇是 JavaScript 逆向爬取的第二篇。那么接下来我为大家缕顺一下学习顺序。系列文章的第一篇启于总结一些网站加密和混淆技术,这篇文章我们介...
  • JsSpider:js逆向-源码

    2021-05-31 09:04:53
    Python3 Spider Author :smiling_face_with_sunglasses:11:smiling_face_with_sunglasses: Email :heart_suit::heart_suit: QQ :heart_suit:1399569097:heart_suit: 一、案例 :dolphin:最后 本项目不定期更新, 如果...
  • 爬虫高阶必备,JavaScript逆向,收藏在看

    千次阅读 多人点赞 2019-05-30 11:30:00
    js逆向是让爬虫萌新们比较头疼的一块领域,因为市面上大部分的爬虫书籍等教程都未涉及这方面知识,需要爬取用js加密的网站时常常无从下手,只能使用selenium等自动化框架来模拟人工点击。但这种方式往往效率低下,...
  • JS逆向」工具篇——Chrome DevTools

    千次阅读 2020-08-23 01:04:12
    文章目录说明常见的逆向需求Chrome DevTools使用说明Elements简单的静态分析:Event Listener93-452g]...png)Dom动态分析:DOM Breakpoints
  • JavaScript 逆向的学习是一件很有意思的事情,大家都知道软件开发是正向思维,但是学习逆向的好处想必行内人都懂,快捷的掌握,然后爬虫。。。当然这个课程大部分人学习了逆向系列课,但是高阶的,哈哈,还真是学的...
  • JS逆向 房天下登录RSA

    2020-12-23 00:28:38
    2.我们跟进去加密函数,代码格式化,RSA.min.js,明显就是 RSA算法,我们把所有的 js拷贝出来 3.我们分析key_to_encode,我们全局搜索一下,可以搜索到,我们复制下来 4.仿照上面的方式,我们写一
  • 第六节 JavaScript逆向 #以有道翻译为简单例子 第一种:post提交表单 按照post方法可以直接提交表单然后进行json.loads()化输出为dict的python对象得到结果。 第二种:JavaScript逆向(签名验证反爬虫) 简介:签名...
  • 最新某瓜某条js逆向获取_signature参数源码
  • 反爬虫JavaScript 逆向分析之token解密

    千次阅读 2020-10-28 11:12:57
    JavaScript 逆向分析 前言:此次分析的是一个大佬的反爬虫练习平台的第6题,是一个电影数据网站,数据通过 Ajax 加载,数据接口参数加密且有时间限制,源码经过混淆,适合 JavaScript 逆向分析。 url = ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,446
精华内容 8,978
关键字:

js逆向