其他分享
首页 > 其他分享> > 猿人学web端爬虫攻防大赛赛题解析_第十八题:jsvmp-洞察先机

猿人学web端爬虫攻防大赛赛题解析_第十八题:jsvmp-洞察先机

作者:互联网

jsvmp-洞察先机

一、前言

又是很长时间没更博客了,今天终于花时间把最后一题给解决了,至此猿人学赛题的学习基本告一段落,总的来说大部分题对我来说都很有挑战性,而每次解题过程中也会学到点新知识。目前的达到的水准是即使有些完全没思路的加密,看下其他大神分享的解题过程,基本上自己也能摸索着还原出来,虽然距离大佬们还有不小的差距,但相比起挑战习题最初的我来说,还算是有一定进步了。总之也算是完成了猿人学赛题的挑战目标,嗯,废话不多说,进入正题。

二、解析过程分析

首选进主页,发现这题内容上跟以往其他题没太大区别,都是抓取数字,不过这题明确说了是jsvmp加密,网上搜了一番也没找到比较好的教程资料,但总之可以确定的是加密很难破解,再就是可以确定加密代码是在虚拟机环境运行,不那么好调试。
在这里插入图片描述打开调试模式,观察一下请求内容,发现请求第一页时没有加密参数,从第二页开始,url会携带t和v两个参数,这里v应该是加密字符串了。
在这里插入图片描述继续观察请求主页源代码,发现这么一大串看着很费劲的js代码,推测加密参数应该就是在这里生成的。
在这里插入图片描述
一番调试后,发现最终请求数返回值是在执行完xml.open这个函数后得到的:

xml.open('GET', location.href + 'data?page=' + page, true);

在这里插入图片描述
xml.open其实就是混淆代码里的y__函数,也就是说加密参数应该是在这里生成的。
在这里插入图片描述
观察一下,变量u__是一个数组,从其第二个元素里可以看到AES的字样,看出是用了AES加密。
在这里插入图片描述虽然知道是什么加密,但是这里是真的很不好调试,没法像很多常规加密那样追踪调用栈来看AES加密前都调用了哪些函数,因为调试过程中大部分代码都会跳转回这个函数,这里参照了一个大佬分享的思路,即hook一下AES加密函数,在加密过程中打印出相关加密信息:
在这里插入图片描述成功hook到加密函数以后,打印一下加密函数传进去的几个参数,然后发现待加密文本text的值是页码加一串有特殊规律的字符串,key和iv的值相同。
在这里插入图片描述
那么这些参数到底是怎么生成的呢,这个时候就可以看看调用栈了,查看调用栈往上走,进入这个_y__函数:
在这里插入图片描述点击进入,跳转到了图下这一行,鼠标放在这里可以看出,被hook的加密函数就在这里。
在这里插入图片描述找到加密位置以后,还是不太好观察参数都是怎么传进去的,于是在这里设置一个日志断点,让代码运行到这里的时候自动输出我们想要观察的参数。
在这里插入图片描述
然后当鼠标在主页滑动时,可以发现控制台会不停输出新的内容
在这里插入图片描述结合前期调试时发现的u__数组内的mouses对象,可以确定这串数组内容就是鼠标的移动轨迹值,这个轨迹值是随机的,所以可以随便确定一组,跟请求页码组成待加密的text值。
在这里插入图片描述
确定text值以后,剩下的就是key和iv值的生成逻辑,这里有个简便方法是观察调试过程中日志断点里输出的内容,从这里可以看到一些可疑对象,比如调试过程中,输出了明显是时间戳的字符串,对时间戳做一定处理后,得到最终的key和iv值。
在这里插入图片描述
这里可以观察到,key和iv值明显是两个相同字符串的加和,而这个字符串又是基于时间戳转换而来,经过验证发现,这里实际上就是把时间戳转换为十六进制,去掉前两位0x后的结果,于是key和iv值也得以确定,这题的加密点也算是找出来了。

乍一看解析过程吧,感觉其实好像不难,但实际上最难的是处理思路,比如一开始能不能想到要hook AES函数,而在这之后又使用日志断点观察加密参数,这也是不熟悉调试工具的情况下很难想到的地方,如果这题靠常规的追调用栈去找加密逻辑,怕是搞到头秃都难以搞清加密逻辑。当然这仅是对于吾等入门级的人而言,可能高手会有更好地解法。

三、代码实现

弄清楚加密逻辑以后,代码实现就比较简单了,直接使用python的AES加密库就行:

from Crypto.Util.Padding import pad, unpad
from Crypto.Cipher import AES
import time
import base64
import requests

headers = {
    'authority': 'match.yuanrenxue.com',
    'pragma': 'no-cache',
    'cache-control': 'no-cache',
    'sec-ch-ua': '"Chromium";v="94", "Google Chrome";v="94", ";Not A Brand";v="99"',
    'sec-ch-ua-mobile': '?0',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36',
    'sec-ch-ua-platform': '"Windows"',
    'accept': '*/*',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-mode': 'cors',
    'sec-fetch-dest': 'empty',
    'referer': 'https://match.yuanrenxue.com/match/18',
    'accept-language': 'zh-CN,zh;q=0.9',
    'cookie': 'Hm_lvt_c99546cf032aaa5a679230de9a95c7db=1635170677,1635258075,1635304521,1635306736; no-alert3=true; Hm_lpvt_c99546cf032aaa5a679230de9a95c7db=1635339533',
}

for i in range(1,6):
    #构造有鼠标轨迹构成的text值,鼠标移动轨迹可以固定
    text='{0}|756d354,756d354,756u354,756u354'.format(str(i))
    byte_text = bytes(text, encoding="utf-8")#转换为字节形式

    #将时间戳转换为KEY,iv
    t = int(time.time())
    iv=hex(t)[2:]*2
    byte_iv=bytes(iv, encoding="utf-8")
    byte_key=byte_iv


    # 初始化加密器,使用CBC模式进行加密
    cryptor =AES.new(byte_key, AES.MODE_CBC,byte_iv)
    enc_result=base64.b64encode(cryptor.encrypt(pad(byte_text,16)))


    params = (
        ('page', str(i)),
        ('t', str(t)),
        ('v', str(enc_result,'utf-8')),
    )

    response = requests.get('https://match.yuanrenxue.com/match/18data', headers=headers, params=params)
    print(response.json())

请求输出结果如下:

{'status': '1', 'state': 'success', 'data': [{'value': 8944}, {'value': 4564}, {'value': 7199}, {'value': 8411}, {'value': 1811}, {'value': 2058}, {'value': 131}, {'value': 3398}, {'value': 115}, {'value': 3819}]}
{'status': '1', 'state': 'success', 'data': [{'value': 5183}, {'value': 7979}, {'value': 5907}, {'value': 5889}, {'value': 7532}, {'value': 5075}, {'value': 3963}, {'value': 9235}, {'value': 4401}, {'value': 2151}]}
{'status': '1', 'state': 'success', 'data': [{'value': 6036}, {'value': 8475}, {'value': 8476}, {'value': 9654}, {'value': 2602}, {'value': 9780}, {'value': 3552}, {'value': 8938}, {'value': 8192}, {'value': 350}]}
{'status': '1', 'state': 'success', 'data': [{'value': 9945}, {'value': 7245}, {'value': 6307}, {'value': 2850}, {'value': 8055}, {'value': 1846}, {'value': 3398}, {'value': 6228}, {'value': 2306}, {'value': 2003}]}
{'status': '1', 'state': 'success', 'data': [{'value': 8147}, {'value': 220}, {'value': 2509}, {'value': 9079}, {'value': 2371}, {'value': 6805}, {'value': 6272}, {'value': 5763}, {'value': 7494}, {'value': 7466}]}

四、参考文献

1、猿人学第十八题(jsvmp)题解
2、vvv 大佬的 jsvm(猿人学18 及 新版本)

标签:web,AES,加密,text,赛题,value,iv,byte,jsvmp
来源: https://blog.csdn.net/qq_38017966/article/details/121002179