正文共:2533 字 10 图
预计阅读时间: 7 分钟
作者:ThreeTails
原 文: http://www.threetails.xyz/2019/05/19/初探js逆向(二)
· 正 · 文 · 来 · 啦 ·
前言
=====
如果你是没有任何 js 逆向经验的爬虫萌新,且没看过上篇的《JavaScript逆向教程,不来了解一下么?》,建议先移步去看,因为本篇所使用的案例相对上篇,难度会更大一些。
在上一篇中,我们学习了一个入门案例的逆向流程。然而,加密的方式有很多,不可能以一概全。在进入本篇正题前,我们先回忆一下上篇的逆向思路:
…
不妨思考一下,参数虽做了加密,但网页毕竟要正常显示内容,所以在网页渲染的过程中,一定有个地方对这个参数做了解密,然后将数据写入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请求里打上断点,刷新一下网页。
代码执行到了 h.send(f)
,等等,好像哪里不对。send 不就是把请求发送出去吗?那是不是意味着请求参数在这步之前就已经生成完毕?观察一下上面几行代码,果然如此:
1558181366544
在 t
对象的 url 属性中可以看到,analysis 已经生成好了。那么我们再往下执行也没意义了,因为这个请求已经被发送到了服务端,客户端没必要再对它的参数进行解密。况且我们的目的是研究如何生成 analysis,而不是如何解密。
那怎样才能找到生成 analysis 的位置呢?我们可以先把它的值记录下来,
fGR5SX10dQ0oY3lVeGIkBH1HDQ1wExcWVlYPG1sAQltVRGJRXlMkFAxXBANUAQUHBQQFcBtV
然后把断点打在一个比较早的地方(analysis 生成之前),一步步往下执行,这个值首次出现的位置,就是它生成的位置。
想把断点打在 analysis 生成之前,可以在 Network 选项卡下,该请求的 Initiator 列里看到它的调用栈,调用顺序由上而下:
1558182881027
在前几条里随便选一个,点进去打上断点,这里我看get
比较顺眼,就选了这条,并在默认位置打上断点。打上断点后别急着刷新网页,这里有个坑需要先避一下。因为除了marketRank
之外,marketList
这个请求也有一个 analysis 参数,它请求的是应用商店列表(百度、应用宝、360…)。为了避免干扰,我们不要刷新网页,而是切换类别:
通过这种方式来触发调试界面,就不会再去请求应用商店列表了。切换类别后即可触发弹出调试界面:
1558183179819
可以发现,简单三参都已经出现了,但还没发现 analysis,它应该还没生成,让我们继续往下执行。注意,执行过程中时刻关注是否出现类似(切换了类别,analysis肯定会变化,所以是类似)我们之前记录下来的那个值。
此处省略一万步调试……,只要你耐心足够,就能找到下图中的代码:
1558184945255
可以看到,r
的值与我们之前记录的值很类似,为了进一步确定,可以在调试执行完成后看下请求中的 analysis 值是否与这个 r
的值一致。
答案是一致的。也就是说,接下来只要把 r
的生成代码全部抠下来,我们就能生成 analysis 了。感觉也没那么难对吧?其实这个网站,抠代码才是重头戏。
抠代码
开头中提到,本案例即便找到了加密位置,也只完成了一半工作。因为加密函数中做了大量的代码混淆和迷惑眼球的函数调用,想把它完整抠下来也不是件容易的事。如果你没有强大的心脏和足够的耐心,请止步于此;但如果你就喜欢折腾,请接着往下看。
鉴于本文的目的主要在于介绍‘请求参数被加密时的逆向思路’,所以不会对‘抠代码’的部分做详细讲解,也不会提供完整代码,但会稍微做一些提示,希望能对你有所帮助。以下提示内容只有真正去尝试抠代码的人才能看懂了。
b
写死。抠出
e
的生成函数,生成e
。
- 时间戳与写死的-44
- 抠出
m
的生成函数,通过简单三参+URL 后缀+e
生成m
。
简单三参 sort 与 join
忽略迷惑代码
ano[Ao]…
进入 e 内部打断点
只关注被调用并执行的代码
new一个Unit8Array
找到写入Unit8Array的代码
转base64
封装
f[La]
,便于步骤4调用
- 抠出
r
的生成函数,通过m
和b
生成r
。
搞定步骤3之后心态千万不要崩,因为胜利就在眼前
几个写死的变量
String["fromCharCode"]
贴张逆向成功的截图:
总结
当请求的参数被加密时,将断点打在加密参数生成之前,在它的值首次出现的位置找到它的加密函数。
抠代码时,如果代码做了大量混淆。需要辨别哪些代码是迷惑你的,哪些代码是真正起作用的,哪些代码是不需要抠的,哪些代码是可以自己用其他方式替代的。
大周末的在家研究js破解,辛苦作者了。
扫码关注,不迷路哦!
猜你喜欢
这顶海贼王的帽子,我Python给你带上了 | 【人脸识别应用】
本文分享自微信公众号 - Python学习开发(python3-5)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。