目标
考点:js 混淆 - 源码乱码
题目1:抓取所有(5页)机票的价格,并计算所有机票价格的平均值,填入答案。
https://match.yuanrenxue.com/match/1
分析
无限debugger
按下f12
,就见到了到debugger
,然后就是无限console
,分别解决掉它们
debugger:一律不在此处暂停
容易栈溢出,导致卡顿
console:使用FD
本地替换
请求
通过网络请求找到价格接口
#第一页
https://match.yuanrenxue.com/api/match/1?m=198fda140e60831667d4593cd8a444ec%E4%B8%A81663855939
#第二页
https://match.yuanrenxue.com/api/match/1?page=2&m=278a90a0e05a38797776e118f40c1be1%E4%B8%A81663856478
接口参数中有一个m
加密,去调用堆栈跟一下
编码请求代码
简单的unicode
混淆,将代码保存下来,使用python转换一下编码就可了。
# ==================================
# --*-- coding: utf-8 --*--
# @Time : 2022/9/21 17:15
# @Author : Gorkys
# @FileName: match_1.py
# @Software: PyCharm
# @describe: 猿人学第一题
# ==================================
with open("1.js", "r", encoding="utf-8") as file_1:
file_1_res = file_1.read()
s = file_1_res.encode('utf-8').decode("unicode_escape")
with open("1_de.js", "w", encoding="utf-8") as file_2:
file_2.write(s)
解码后,可以很清晰的看见m
的组成。(后面发现在https://www.sojson.com/中美化代码就可以直接转换编码)
解密
解读一下代码
_0x2268f9 = 当前时间的时间戳(不含毫秒13位)+ (16798545 + -72936737 + 156138192)
其中后面的计算得出为:100000000
结果 = _0x2268f9.toString()
加密(结果)+ window['f']
其中window['f']
在控制台打印一下,得到字符串:c512e7663ac285e462b493106df106fd
然后再全局搜索一下oo0O0
方法,发现就在html的<script>
中,先将html
格式化,再将目标代码格式化掉。
先看结尾处返回的是一个空,所以这个函数本身是不会返回有用的结果,那么在上面的代码中肯定是对window.f
做什么手脚
for
循环赋值给window.b
逻辑上是在组装着什么,去控制台打印一下结果。
window.b
本身是被base64加密过,在后面的eval
代码也可以看出使用了atob
解密执行。
注意到最后的window.f=hex_md5(mwqqppz)
,果然,用md5
加密了一个值赋给了window.f
,继续看后面的代码,通过解密函数J
解密后得到如下明文
eval(atob(window['b'])['replace']('mwqqppz', '\x27' + mw + '\x27'));
也就是说是将mwqqppz
替换成了之前通过计算传入的时间戳。\x27
编码后为单引号。所以最终加密的是'时间戳'
完整代码
# ==================================
# --*-- coding: utf-8 --*--
# @Time : 2022/9/21 17:15
# @Author : Gorkys
# @FileName: match_1.py
# @Software: PyCharm
# @describe: 猿人学第一题
# ==================================
# with open("1.js", "r", encoding="utf-8") as file_1:
# file_1_res = file_1.read()
# s = file_1_res.encode('utf-8').decode("unicode_escape")
# with open("1_de.js", "w", encoding="utf-8") as file_2:
# file_2.write(s)
import requests
import time
import execjs
with open("md5.js", "r", encoding="utf-8") as file:
js = file.read()
def getSign():
int_t = int(int(time.time()) * 1e3) + int(1e8)
t = int(int_t / 1e3)
runJs = execjs.compile(js)
sign_tem = runJs.call("hex_md5", f'{str(int_t)}')
return f"{sign_tem}丨{t}"
def getPriceList(page, ua):
headers = {
'referer': 'https://match.yuanrenxue.com/match/1',
'user-agent': ua,
}
params = {
'page': f'{page}',
'm': getSign()
}
response = requests.get('https://match.yuanrenxue.com/api/match/1', params=params, headers=headers)
return response.json()["data"]
userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36'
priceList = []
for i in range(5):
if i + 1 >= 4:
userAgent = "yuanrenxue.project"
priceList += getPriceList(i + 1, userAgent)
priceCount = 0
for i in range(len(priceList)):
priceCount += priceList[i]['value']
print(priceCount / len(priceList))
# 4700.0