大山深处的云 發表於 2020-9-7 18:05:00

JavaScript逆向教程,不来了解一下么?

<p style="text-align: justify; white-space: normal"><span style="color: rgba(136, 136, 136, 1); font-size: 12px">原 文:&nbsp;<span style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif; color: rgba(136, 136, 136, 1); font-size: 12px">http:/<span style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif; color: rgba(136, 136, 136, 1); font-size: 12px">/www.threetails.xyz/2019/05/10/初探js逆向/</span></span></span></p>
<h2 id="h2_1" style="margin: 80px 10px 40px; font-size: 22.4px; white-space: normal; box-sizing: border-box; text-align: center; color: rgba(63, 63, 63, 1); line-height: 1.5; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">前言</h2>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">本文适合爬虫新手阅读,大佬也别绕道,欢迎指正和调教。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">js逆向是让爬虫萌新们比较头疼的一块领域,因为市面上大部分的爬虫书籍等教程都未涉及这方面知识,需要爬取用js加密的网站时常常无从下手,只能使用selenium等自动化框架来模拟人工点击。但这种方式往往效率低下,所以本文将以&nbsp;<span style="color: rgba(255, 41, 65, 1)">企名片<span style="box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5"><sup style="color: rgba(255, 53, 2, 1); font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif; text-align: left; white-space: normal; box-sizing: border-box"></sup><span style="color: rgba(255, 53, 2, 1); font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif; font-size: 13.3333px; text-align: left">这个网站为例,带大家初探js逆向。</span></span></span></p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">之所以选择这个网站,首先它难度不大,适合练手;其次即便破解了加密参数,想爬取数据还是得下些功夫,因为未登录情况下只显示一页数据,即便登录还得认证啥的比较麻烦。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">废话不多说,下面进入正题。</p>
<h2 id="h2_2" style="margin: 80px 10px 40px; font-size: 22.4px; white-space: normal; box-sizing: border-box; text-align: center; color: rgba(63, 63, 63, 1); line-height: 1.5; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">环境准备</h2>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">因为涉及js的调试验证,所以除了Python环境外,你还需要<span style="box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5">Nodejs<sup style="box-sizing: border-box"></sup>(js的运行环境)和<span style="box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5">WebStorm<sup style="box-sizing: border-box"></sup>(IDE)。</span></span></p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">Nodejs去官网下载安装包后直接一键安装即可,安装完毕后去控制台运行<code style="padding: 3px 5px; box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5; font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace; font-size: 14.4px; background: rgba(248, 245, 236, 1); border-radius: 2px">node --version</code>,如果出现版本号即代表安装成功。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">WebStorm安装完后需要激活,激活教程网上很多,大家自行搜索。它是Jet Brains的产品(和PyCharm是同一家公司),所以使用方式与PyCharm很类似。</p>
<h2 id="h2_3" style="margin: 80px 10px 40px; font-size: 22.4px; white-space: normal; box-sizing: border-box; text-align: center; color: rgba(63, 63, 63, 1); line-height: 1.5; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">分析过程</h2>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">直接访问这个地址https://www.qimingpian.com/finosda/project/pinvestment,看到的是这个界面:</p>
<p style="white-space: normal; text-align: center"><img class="rich_pages zoom-in-cursor lazyload" data-ratio="0.599694423223835" data-s="300,640" data-type="png" data-w="1309" data-src="https://oscimg.oschina.net/oscnet/c8af64ca-7853-408c-8df3-2f2308fdd010.png"></p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">我们需要获取图中红框里的数据,也就是创业项目列表。打开开发者工具,刷新一下页面,看看它发起了哪些请求:</p>
<p style="white-space: normal; text-align: center"><img class="rich_pages zoom-in-cursor lazyload" data-ratio="0.3175925925925926" data-s="300,640" data-type="png" data-w="1080" data-src="https://oscimg.oschina.net/oscnet/81abd328-abbf-4a9f-8ba9-966765fcc7b0.png"></p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">为减少干扰,先只看XHR和Doc的请求,一共有三个:pinvestment、productListVip、industryFieldVip。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">在pinvestment的响应内容里,只能看到一堆js的调用,并没有我们想要的html,说明网页是由js动态生成的。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">而在productListVip和industryFieldVip的响应内容里,都有一个"encrypt_data"的参数,很明显这是一个加密参数,参数内容像是一串Base64字符。既然网站对这个参数做了加密,说明它不想被爬取,所以可以做个假设:我们的目标数据就是encrypt_data参数里的内容。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">有了这个假设,目的就很明确了,只要破解这个加密参数就行。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">爬虫新手们往往走完上面步骤就止步不前。不妨思考一下,参数虽做了加密,但网页毕竟要正常显示内容,所以在网页渲染的过程中,一定有个地方对这个参数做了解密,然后将数据写入html。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">也就是说,我们需要在网页渲染的过程里,一步步观察,看看到底是哪个位置对这个参数做了解密。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">在开发者工具里的Sources选项卡中,可以找到这个网页的js文件夹,界面右侧有断点调试栏。</p>
<p style="text-align: center"><img class="rich_pages zoom-in-cursor lazyload" data-ratio="0.41802575107296136" data-s="300,640" data-type="png" data-w="1165" data-src="https://oscimg.oschina.net/oscnet/879a2aaa-8d47-48b4-860b-908448bb5d3d.png"></p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">在js文件里打上断点,然后一步步调试,就能重现网页渲染的过程。那么断点应该打在哪个位置呢?在断点调试栏里有个XHR/fetch Breakpoints,它支持在发送XHR请求的位置打上断点,我们找到的两个含加密参数的请求就是XHR类型的,正好用上这个功能。点击<code style="padding: 3px 5px; box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5; font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace; font-size: 14.4px; background: rgba(248, 245, 236, 1); border-radius: 2px">+</code>号输入请求名称即可:</p>
<p style="white-space: normal; text-align: center"><img class="rich_pages zoom-in-cursor lazyload" data-ratio="0.5" data-s="300,640" data-type="png" data-w="322" data-src="https://oscimg.oschina.net/oscnet/411e7406-6a02-49a0-a7b8-40b82c8b2c5c.png"></p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">刷新页面,然后一步一步执行,发现可疑信息就把鼠标移上去看下。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif"><img class="rich_pages zoom-in-cursor lazyload" style="text-align: center" data-ratio="0.347114556416882" data-s="300,640" data-type="png" data-w="1161" data-src="https://oscimg.oschina.net/oscnet/30e2e442-3c50-4a1f-bb8e-c08b1e56bc47.png"></p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">调试的两个小技巧:</p>
<p style="margin-top: 20px; margin-right: 10px; margin-bottom: 20px; padding-left: 20px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.5; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif; list-style: circle"><span style="margin: 10px; box-sizing: border-box; line-height: 1.5; text-indent: -20px; display: block"><span style="margin-right: 10px; box-sizing: border-box">•压缩的js点击左下角的花括号来美化</span></span></p>
<p style="white-space: normal; text-align: center"><img class="rich_pages zoom-in-cursor lazyload" data-ratio="0.6631823461091754" data-s="300,640" data-type="png" data-w="861" data-src="https://oscimg.oschina.net/oscnet/4a9cf13d-6aff-4ae8-aa3a-48a4d006c594.png"></p>
<p style="margin-top: 20px; margin-right: 10px; margin-bottom: 20px; padding-left: 20px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.5; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif; list-style: circle"><span style="margin: 10px; box-sizing: border-box; line-height: 1.5; text-indent: -20px; display: block"><span style="margin-right: 10px; box-sizing: border-box">•在调试过程中使用Console执行js代码。比如我觉得这个函数很可疑,想执行一下看看。</span></span></p>
<p style="white-space: normal; text-align: center"><img class="rich_pages zoom-in-cursor lazyload" data-ratio="0.885685884691849" data-s="300,640" data-type="png" data-w="1006" data-src="https://oscimg.oschina.net/oscnet/a6275e74-7311-498b-9abb-d91211d1e865.png"></p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">其实上图中执行<code style="padding: 3px 5px; box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5; font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace; font-size: 14.4px; background: rgba(248, 245, 236, 1); border-radius: 2px">Object(d.a)(e.encrypt_data)</code>返回的内容就是我们需要的数据了。进到这个函数体里边,就能找到解密函数:</p>
<p style="white-space: normal; text-align: center"><img class="rich_pages zoom-in-cursor lazyload" data-ratio="0.6921269095182139" data-s="300,640" data-type="png" data-w="851" data-src="https://oscimg.oschina.net/oscnet/6ffad060-c2ff-4c50-a587-a2f907363a43.png"></p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif"><code style="padding: 3px 5px; box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5; font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace; font-size: 14.4px; background: rgba(248, 245, 236, 1); border-radius: 2px">function o(t)</code>就是我们需要的解密函数,可以看到它先调用<code style="padding: 3px 5px; box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5; font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace; font-size: 14.4px; background: rgba(248, 245, 236, 1); border-radius: 2px">s</code>函数,传入了四个参数,除了<code style="padding: 3px 5px; box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5; font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace; font-size: 14.4px; background: rgba(248, 245, 236, 1); border-radius: 2px">a.a.decode(t)</code>外其他三个都是写死的,最后用<code style="padding: 3px 5px; box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5; font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace; font-size: 14.4px; background: rgba(248, 245, 236, 1); border-radius: 2px">JSON.parse</code>转为json对象。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">然而,找到解密函数后,我们要做的不是去分析它函数内部做了什么,虽然可以研究它的解密算法然后用Python重写,但这样太复杂且没必要。因为我们可以用<span style="box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5">PyExecJS<sup style="box-sizing: border-box"></sup>这个库,直接用Python调用并执行js代码。</span></p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">这时候,WebStorm就派上用场了。新建一个js文件,把<code style="padding: 3px 5px; box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5; font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace; font-size: 14.4px; background: rgba(248, 245, 236, 1); border-radius: 2px">function o</code>里涉及的代码全部抠下来。然后执行<code style="padding: 3px 5px; box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5; font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace; font-size: 14.4px; background: rgba(248, 245, 236, 1); border-radius: 2px">console.log</code>把执行结果打印出来。篇幅问题就只贴部分代码:</p>
<pre class="code-snippet__js" data-lang="javascript"><code class="hljs rust" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box"><span class="hljs-comment">//解密函数</span></span></code><code class="hljs javascript" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box"><span class="hljs-function"><span class="hljs-keyword">function <span class="hljs-title">my_decrypt(<span class="hljs-params">t) {</span></span></span></span></span></code><code class="hljs kotlin" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">    <span class="hljs-keyword">return JSON.parse(s(<span class="hljs-string">"5e5062e82f15fe4ca9d24bc5", my_decode(t), <span class="hljs-number">0, <span class="hljs-number">0, <span class="hljs-string">"012345677890123", <span class="hljs-number">1))</span></span></span></span></span></span></span></code><code class="hljs" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">}</span></code><code class="hljs" style="box-sizing: border-box"><span class="code-snippet_outer"><br></span></code><code class="hljs rust" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box"><span class="hljs-comment">//解密函数依赖项</span></span></code><code class="hljs javascript" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box"><span class="hljs-function"><span class="hljs-keyword">function <span class="hljs-title">my_decode(<span class="hljs-params">t) {</span></span></span></span></span></code><code class="hljs swift" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">    <span class="hljs-built_in">c = <span class="hljs-string">"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"</span></span></span></code><code class="hljs properties" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">    <span class="hljs-attr">f = <span class="hljs-string">/[\t\n\f\r ]/g</span></span></span></code><code class="hljs typescript" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">    <span class="hljs-keyword">var e = (t = <span class="hljs-built_in">String(t).replace(f, <span class="hljs-string">"")).length;</span></span></span></span></code><code class="hljs coffeescript" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">    e % <span class="hljs-number">4 == <span class="hljs-number">0 &amp;&amp; (e = (t = t.replace(<span class="hljs-regexp">/==?$/, <span class="hljs-string">"")).length),</span></span></span></span></span></code><code class="hljs yaml" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">    <span class="hljs-string">(e <span class="hljs-string">% <span class="hljs-number">4 <span class="hljs-string">== <span class="hljs-number">1 <span class="hljs-string">|| <span class="hljs-string">/[^+a-zA-Z0-9/]/.test(t)) <span class="hljs-string">&amp;&amp; <span class="hljs-string">l("Invalid <span class="hljs-attr">character: <span class="hljs-string">the <span class="hljs-string">string <span class="hljs-string">to <span class="hljs-string">be <span class="hljs-string">decoded <span class="hljs-string">is <span class="hljs-string">not <span class="hljs-string">correctly <span class="hljs-string">encoded.");</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code><code class="hljs less" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">    <span class="hljs-selector-tag">for (var n, r, i = <span class="hljs-number">0, o = <span class="hljs-string">"", a = -<span class="hljs-number">1; ++a &lt; e; )</span></span></span></span></span></code><code class="hljs properties" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">      <span class="hljs-attr">r = <span class="hljs-string">c.indexOf(t.charAt(a)),</span></span></span></code><code class="hljs yaml" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">            <span class="hljs-string">n <span class="hljs-string">= <span class="hljs-string">i <span class="hljs-string">% <span class="hljs-number">4 <span class="hljs-string">? <span class="hljs-number">64 <span class="hljs-string">* <span class="hljs-string">n <span class="hljs-string">+ <span class="hljs-attr">r : <span class="hljs-string">r,</span></span></span></span></span></span></span></span></span></span></span></span></span></code><code class="hljs yaml" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">      <span class="hljs-string">i++ <span class="hljs-string">% <span class="hljs-number">4 <span class="hljs-string">&amp;&amp; <span class="hljs-string">(o <span class="hljs-string">+= <span class="hljs-string">String.fromCharCode(255 <span class="hljs-string">&amp; <span class="hljs-string">n <span class="hljs-string">&gt;&gt; <span class="hljs-string">(-2 <span class="hljs-string">* <span class="hljs-string">i <span class="hljs-string">&amp; <span class="hljs-number">6<span class="hljs-string">)));</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code><code class="hljs kotlin" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">    <span class="hljs-keyword">return o</span></span></code><code class="hljs" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">}</span></code><code class="hljs" style="box-sizing: border-box"><span class="code-snippet_outer"><br></span></code><code class="hljs rust" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box"><span class="hljs-comment">//测试代码,加密参数太长就不贴上来了</span></span></code><code class="hljs makefile" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">encrypt_data = <span class="hljs-string">"xxx"</span></span></code><code class="hljs makefile" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">decrypt_data = my_decrypt(encrypt_data)</span></code><code class="hljs less" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box"><span class="hljs-selector-tag">console<span class="hljs-selector-class">.log(decrypt_data)</span></span></span></code></pre>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">执行结果:</p>
<p style="white-space: normal; text-align: center"><img class="rich_pages zoom-in-cursor lazyload" data-ratio="0.3503355704697987" data-s="300,640" data-type="png" data-w="745" data-src="https://oscimg.oschina.net/oscnet/fa5f1ee6-f5bf-4a4f-a964-6b381e46cbf0.png"></p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">确实是我们需要的数据没错,最后用Python去调用解密函数就行了。调用时还有个需要注意的地方,因为直接返回object给Python会报错,所以这里将JSON.parse移除了,返回parse前的json字符串,</p>
<pre class="code-snippet__js" data-lang=""><code class="hljs rust" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box"><span class="hljs-comment">//解密函数</span></span></code><code class="hljs javascript" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box"><span class="hljs-function"><span class="hljs-keyword">function <span class="hljs-title">my_decrypt(<span class="hljs-params">t) {</span></span></span></span></span></code><code class="hljs kotlin" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">    <span class="hljs-keyword">return s(<span class="hljs-string">"5e5062e82f15fe4ca9d24bc5", my_decode(t), <span class="hljs-number">0, <span class="hljs-number">0, <span class="hljs-string">"012345677890123", <span class="hljs-number">1)</span></span></span></span></span></span></span></code><code class="hljs" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">}</span></code></pre>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">同时为了防止这串字符串内有特殊编码的字符,这里将它转成base64再return:</p>
<pre class="code-snippet__js" data-lang=""><code class="hljs javascript" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box"><span class="hljs-function"><span class="hljs-keyword">function <span class="hljs-title">my_decrypt(<span class="hljs-params">t) {</span></span></span></span></span></code><code class="hljs less" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">    <span class="hljs-selector-tag">return <span class="hljs-selector-tag">new <span class="hljs-selector-tag">Buffer(s(<span class="hljs-string">"5e5062e82f15fe4ca9d24bc5", my_decode(t), <span class="hljs-number">0, <span class="hljs-number">0, <span class="hljs-string">"012345677890123", <span class="hljs-number">1))<span class="hljs-selector-class">.toString(<span class="hljs-string">"base64")</span></span></span></span></span></span></span></span></span></span></span></code><code class="hljs" style="box-sizing: border-box"><span class="code-snippet_outer" style="box-sizing: border-box">}</span></code></pre>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">然后在Python中用base64库的b64decode方法来解码即可。</p>
<h2 id="h2_4" style="margin: 80px 10px 40px; font-size: 22.4px; white-space: normal; box-sizing: border-box; text-align: center; color: rgba(63, 63, 63, 1); line-height: 1.5; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">总结</h2>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">最后总结一下,说说关于逆向的个人看法。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">之所以市面上很少有爬虫逆向的书籍,除了因为它比较"敏感"之外,也因为它并没有固定的方法论。上文提供的也只是一种思路,其实还是有很多取巧的方式,比如在我们已知参数名为<code style="padding: 3px 5px; box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5; font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace; font-size: 14.4px; background: rgba(248, 245, 236, 1); border-radius: 2px">encrypt_data</code>的情况下,在js文件夹下全局搜索,分分钟就能找到解密函数。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">逆向过程挺糟心,也挺有趣的,且逆向成功后会有很大的成就感。</p>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; font-size: 16px; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.6; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">总而言之,逆向是一个提出假设和实际验证的过程,比如上文中的<code style="padding: 3px 5px; box-sizing: border-box; color: rgba(255, 53, 2, 1); line-height: 1.5; font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace; font-size: 14.4px; background: rgba(248, 245, 236, 1); border-radius: 2px">encrypt_data</code>,我们不能百分百确定它就是我们需要的数据,但可以假设它是,来作为我们的突破口,即便最后发现不是,大不了再做新的假设。这有点像侦探探案,通过已知的信息作为线索来抽丝剥茧,最终破案。</p>
<h3 id="h3_5" style="margin: 40px 10px 20px; font-weight: bold; font-size: 19.2px; white-space: normal; box-sizing: border-box; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.5; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif">References</h3>
<p style="margin: 10px; white-space: normal; box-sizing: border-box; text-align: left; color: rgba(63, 63, 63, 1); line-height: 1.5; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif; font-size: 14px"><code style="box-sizing: border-box; font-size: 12.6px; opacity: 0.6"></code>&nbsp;企名片:&nbsp;<em style="box-sizing: border-box">https://www.qimingpian.com/finosda/project/pinvestment</em><br style="box-sizing: border-box"><code style="box-sizing: border-box; font-size: 12.6px; opacity: 0.6"></code>&nbsp;Nodejs:&nbsp;<em style="box-sizing: border-box">https://nodejs.org/en/</em><br style="box-sizing: border-box"><code style="box-sizing: border-box; font-size: 12.6px; opacity: 0.6"></code>&nbsp;WebStorm:&nbsp;<em style="box-sizing: border-box">https://www.jetbrains.com/webstorm/</em><br style="box-sizing: border-box"><code style="box-sizing: border-box; font-size: 12.6px; opacity: 0.6"></code>&nbsp;PyExecJS:&nbsp;<em style="box-sizing: border-box">https://pypi.org/project/PyExecJS/</em><br style="box-sizing: border-box"><code style="box-sizing: border-box; font-size: 12.6px; opacity: 0.6"></code>&nbsp;Github:&nbsp;<em style="box-sizing: border-box">https://github.com/codingZXY/LearnCrackJs/tree/master/qimingpian</em></p><br><br>
来源:https://www.cnblogs.com/jscs/p/13628274.html
頁: [1]
查看完整版本: JavaScript逆向教程,不来了解一下么?