0%

猿人学第一题-JS混淆-源码乱码

猿人学第一题-JS混淆-源码乱码

我们在爆破用户名密码的时候,用户名经常加密,加密混淆js情况也会存在,发现猿人学这个网站可以很好的学习JS对抗,感谢作者出了这么优秀的题目,我们现在看一下第一道题。


做题步骤

首先我们拿到题目,发现为抓取数据求平均值。

我们使用burp抓个包看一下

我们发现他的这个请求数据里面存在机票的价格。
接着我们切换到第二页,我们发现多了一个page参数,它用来控制页数。

我们还发现m参数的值是不断变化的,那么他应该是某个js动态的去生成的,我们去浏览器里面调试跟踪看看。
我们按F12,进入开发者模式,会强制进行的debug。


我们将debug取消掉就可以正常的调试了。
这里我们有两种方式找到调用堆栈。

在网络里面可以看到调用堆栈。


可以点击调用堆栈中的js,去分析源码。

XHR断点

xhr:XMLHttpRequest在后台与服务器交换数据,这意味着可以在不加载整个网页的情况下,对网页某部分的内容进行更新。
因为请求是xhr类型的,所以我们可以使用XHR断点进行调试。

然后我们重新获取一下网站的数据。

我们看到有这几个调用堆栈。逐个去分析代码会发现m的关键生成位置在这个地方。

代码被混淆了,对与这种0x的混淆,还是比较好还原的。可以使用下面的网站进行还原

1
https://tool.lu/js/index.html

还原后得到关键代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(window["url"] =
"/api/" + "match" + "/1"),
(request = function () {
var _0x2268f9 =
Date["parse"](new Date()) +
(16798545 + -72936737 + 156138192),
_0x57feae =
oo0O0(_0x2268f9["toStr" + "ing"]()) +
window["f"];
const _0x5d83a3 = {};
(_0x5d83a3["page"] = window["page"]),
(_0x5d83a3["m"] =
_0x57feae + "丨" + _0x2268f9 / (-1 * 3483 + -9059 + 13542));
var _0xb89747 = _0x5d83a3;

虽然还有混淆,但是已经不妨碍我们读懂逻辑了。
m的生成过程为:

1
_0x5d83a3["m"] =_0x57feae + "丨" + _0x2268f9 / (-1 * 3483 + -9059 + 13542);

也就是

1
_0x5d83a3["m"] =(oo0O0((Date["parse"](new Date()) + (16798545 + -72936737 + 156138192))["toStr" + "ing"]()) + window["f"]) + "丨" + (Date["parse"](new Date()) +(16798545 + -72936737 + 156138192)) / (-1 * 3483 + -9059 + 13542)

在以上关键代码中,我们有些是不认识的,我们使用console.log去查看哪些是局部的哪些是全局的。
我们在控制台执行

1
(oo0O0((Date["parse"](new Date()) + (16798545 + -72936737 + 156138192))["toStr" + "ing"]()) + window["f"]) + "丨" + (Date["parse"](new Date()) +(16798545 + -72936737 + 156138192)) / (-1 * 3483 + -9059 + 13542)

发现全是全局的,那么我们就可以直接使用python的selenium去执行了。

完整代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import json
import time
import urllib
import requests

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_argument("--ignore-certificate-errors")
chrome_options.add_argument("--proxy-server=http://127.0.0.1:8080")
driver = webdriver.Chrome() # 或者 webdriver.Chrome()
driver = webdriver.Chrome(options=chrome_options)
driver.get('https://match.yuanrenxue.cn/match/1')
price=[]

def getdate(i,m):
global price # 声明price为全局变量
url="https://match.yuanrenxue.cn/api/match/1?page={i}&m={m}".format(i=i,m=m)
headers = {"user-agent": "yuanrenxue.project"}
req=requests.get(url,headers=headers)
print(req.text)
data = json.loads(req.text)
values = [item['value'] for item in data['data']]
price=price+values

for i in range (1,6):
exec="""var m = (oo0O0((Date["parse"](new Date()) + (16798545 + -72936737 + 156138192))["toStr" + "ing"]()) + window["f"]) + "丨" + (Date["parse"](new Date()) +(16798545 + -72936737 + 156138192)) / (-1 * 3483 + -9059 + 13542);
return m"""
result = driver.execute_script(exec)
result= urllib.parse.quote(result)
getdate(i,result)
time.sleep(2)

average = sum(price) / len(price)
print(average)
driver.quit()

tips

  • 调用网站的js去获取变量值,肯定不如直接将关键js抠出来去执行效率高,这个后续去做。
  • 虽然这些训练都是针对爬虫的训练,但是网站安全中的这些js对抗都是差不多。比如用户名密码加密这些操作。