猿人学第9题js混淆-动态cookie2
@ -16,7 +16,7 @@ document[$b('\x30\x78\x31\x33\x31', '\x4d\x45\x47\x72') + $b('\x30\x78\x34\x37',
|
|||||||
|
|
||||||
修改后
|
修改后
|
||||||
```javascript
|
```javascript
|
||||||
document['cookie'] = 'm=' + '2' + res + '; path=/';
|
document['cookie'] = 'm=' + (m - 1)['toString']() + res + '; path=/';
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
@ -28,14 +28,46 @@ document['cookie'] = 'm=' + '2' + res + '; path=/';
|
|||||||

|

|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
res = f[$b('\x30\x78\x31\x33\x65', '\x25\x25\x41\x48') + '\x5a\x79'](f[$b('\x30\x78\x34\x32', '\x54\x35\x5b\x4f') + '\x41\x42'](decrypt, '1693274196'), '\x72');
|
for (var m = 0x1; f[$b('\x30\x78\x31\x37\x36', '\x77\x39\x24\x39') + '\x69\x59'](m, 5); m++) {
|
||||||
|
if (f['\x4e\x6c\x53' + '\x6e\x78'](f['\x64\x48\x6d' + '\x56\x6d'], f[$b('\x30\x78\x31\x30\x64', '\x62\x5a\x32\x76') + '\x56\x6d'])) {
|
||||||
|
res = f[$b('\x30\x78\x31\x35\x61', '\x62\x5a\x32\x76') + '\x49\x71'](decrypt('1693299477'), '\x72');
|
||||||
|
} else {
|
||||||
|
var p = fn[$b('\x30\x78\x66\x61', '\x6c\x33\x5a\x57') + '\x6c\x79'](context, arguments);
|
||||||
|
fn = null;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
修改后
|
修改后
|
||||||
```javascript
|
```javascript
|
||||||
|
for (var m = 1; m <= 5; m++) {
|
||||||
res = decrypt('1693276453') + 'r';
|
res = decrypt('1693276453') + 'r';
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
这里多刷新几次,你会发现for循环的次数是不固定的,通过后端返回,后期编写爬虫代码时就需要将`m`解析下来。
|
||||||
|
|
||||||
|
第一次返回的是5
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
第二次返回的是3
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
完整的cookie生成代码
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
for (var m = 1; m<=3; m++) {
|
||||||
|
res = decrypt('1693300807') + 'r';
|
||||||
|
}
|
||||||
|
|
||||||
|
document['cookie'] = 'm=' + (m - 1)['toString']() + res + '; path=/';
|
||||||
|
```
|
||||||
|
|
||||||
|
## `decryp`是怎么来的
|
||||||
|
|
||||||
通过控制台可以看出函数`decrypt`是udc.js文件生成的。
|
通过控制台可以看出函数`decrypt`是udc.js文件生成的。
|
||||||
|
|
||||||
继续进入,打上断点,可以看到这样一段代码
|
继续进入,打上断点,可以看到这样一段代码
|
||||||
@ -54,7 +86,7 @@ function _0x4f6d79(_0x50f9fa) {
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
目前还原后的代码就是
|
还原后的代码就是
|
||||||
```javascript
|
```javascript
|
||||||
function decrypt(_0x50f9fa) {
|
function decrypt(_0x50f9fa) {
|
||||||
const _0x506402 = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5GVku07yXCndaMS1evPIPyWwhbdWMVRqL4qg4OsKbzyTGmV4YkG8H0hwwrFLuPhqC5tL136aaizuL/lN5DRRbePct6syILOLLCBJ5J5rQyGr00l1zQvdNKYp4tT5EFlqw8tlPkibcsd5Ecc8sTYa77HxNeIa6DRuObC5H9t85ALJyDVZC3Y4ES/u61Q7LDnB3kG9MnXJsJiQxm1pLkE7Zfxy29d5JaXbbfwhCDSjE4+dUQoq2MVIt2qVjZSo5Hd/bAFGU1Lmc7GkFeLiLjNTOfECF52ms/dks92Wx/glfRuK4h/fcxtGB4Q2VXu5k68e/2uojs6jnFsMKVe+FVUDkQIDAQAB';
|
const _0x506402 = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5GVku07yXCndaMS1evPIPyWwhbdWMVRqL4qg4OsKbzyTGmV4YkG8H0hwwrFLuPhqC5tL136aaizuL/lN5DRRbePct6syILOLLCBJ5J5rQyGr00l1zQvdNKYp4tT5EFlqw8tlPkibcsd5Ecc8sTYa77HxNeIa6DRuObC5H9t85ALJyDVZC3Y4ES/u61Q7LDnB3kG9MnXJsJiQxm1pLkE7Zfxy29d5JaXbbfwhCDSjE4+dUQoq2MVIt2qVjZSo5Hd/bAFGU1Lmc7GkFeLiLjNTOfECF52ms/dks92Wx/glfRuK4h/fcxtGB4Q2VXu5k68e/2uojs6jnFsMKVe+FVUDkQIDAQAB';
|
||||||
@ -70,7 +102,7 @@ document['cookie'] = 'm=' + '2' + res + '; path=/';
|
|||||||
console.log(document);
|
console.log(document);
|
||||||
```
|
```
|
||||||
|
|
||||||
## 找出`JSEncrypt`加密生成逻辑
|
## `JSEncrypt`加密生成逻辑
|
||||||
|
|
||||||
先将`udc.js`中的代码,用`v_jstools`进行16进制转成10进制,全局搜索就找到`JSEncrypt`赋值点,
|
先将`udc.js`中的代码,用`v_jstools`进行16进制转成10进制,全局搜索就找到`JSEncrypt`赋值点,
|
||||||
|
|
||||||
@ -171,8 +203,93 @@ if (_0x41a2bf[_0x56ae("0xe73", "XiWX")](("" + _0x457d14 / _0x457d14)[_0x41a2bf[_
|
|||||||
修改后
|
修改后
|
||||||
```javascript
|
```javascript
|
||||||
if (_0x41a2bf['LRGDx'](("" + _0x457d14 / _0x457d14)['length'], 1) || (_0x457d14 % 20) === 0) {
|
if (_0x41a2bf['LRGDx'](("" + _0x457d14 / _0x457d14)['length'], 1) || (_0x457d14 % 20) === 0) {
|
||||||
|
'debugger'
|
||||||
} else {
|
} else {
|
||||||
|
'debugger'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
到这里就可以顺利调试了
|
||||||
|
|
||||||
|
## 去除浏览器环境检测代码
|
||||||
|
|
||||||
|
**window环境检测**
|
||||||
|
|
||||||
|
第一处:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
第二处:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
第三处:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**删除多余代码**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**atob检测**
|
||||||
|
|
||||||
|
当你在本地运行时,没有再出现报错信息,但加密的结果值还是不对。这里就要用到`js proxy`代理,通过代理打印检测点。
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
window = this;
|
||||||
|
navigator = {};
|
||||||
|
location = {};
|
||||||
|
document = {};
|
||||||
|
|
||||||
|
// 框架代理功能
|
||||||
|
catvm = {};
|
||||||
|
catvm.proxy = function (o) {
|
||||||
|
return new Proxy(o, {
|
||||||
|
set(target, key, value) {
|
||||||
|
console.log('set-->', target, key, value);
|
||||||
|
return Reflect.set(...arguments);
|
||||||
|
},
|
||||||
|
get(target, key, receiver) {
|
||||||
|
console.log('get-->', target, key, target[key]);
|
||||||
|
return target[key];
|
||||||
|
},
|
||||||
|
deleteProperty: function (target, key) {
|
||||||
|
console.log('delete-->', target, key);
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
window = catvm.proxy(window);
|
||||||
|
navigator = catvm.proxy(navigator);
|
||||||
|
location = catvm.proxy(location);
|
||||||
|
document = catvm.proxy(document);
|
||||||
|
```
|
||||||
|
|
||||||
|
打印信息:
|
||||||
|
|
||||||
|
get--> {} atob undefined
|
||||||
|
set--> {} atob [Function (anonymous)]
|
||||||
|
get--> { atob: [Function (anonymous)] } crypto undefined
|
||||||
|
|
||||||
|
`atob undefined`对应的位置:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
修改成:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
_0x4f1af6.atob
|
||||||
|
```
|
||||||
|
|
||||||
|
`crypto undefined`对应的位置:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
直接删除即可。
|
||||||
|
|
||||||
|
## python代码运行
|
||||||
|
|
||||||
|
最后爬虫实现
|
||||||
|
|
||||||
|

|
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/10.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/11.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/12.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/13.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/14.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/15.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/16.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/9.png
Normal file
After Width: | Height: | Size: 26 KiB |
@ -17,36 +17,40 @@ class 实例1(object):
|
|||||||
'Cookie': 'sessionid=t9dlfwn9s4ed4z1w1sktxg3k55dc3ko6'
|
'Cookie': 'sessionid=t9dlfwn9s4ed4z1w1sktxg3k55dc3ko6'
|
||||||
}
|
}
|
||||||
response = requests.request("GET", url, headers=headers, data=payload)
|
response = requests.request("GET", url, headers=headers, data=payload)
|
||||||
|
try:
|
||||||
|
m_num = re.findall(r'\(m,([0-9]{1})\);m\+\+\)', response.text)[0]
|
||||||
|
except Exception as e:
|
||||||
|
m_num = re.findall(r'm<=([0-9]{1});m\+\+\)', response.text)[0]
|
||||||
time_str = re.findall(r'decrypt.*?([0-9]{10})', response.text)[0]
|
time_str = re.findall(r'decrypt.*?([0-9]{10})', response.text)[0]
|
||||||
return time_str
|
return time_str, m_num
|
||||||
|
|
||||||
def get_sign(self, date_time):
|
def get_sign(self, date_time, m_num):
|
||||||
data = {
|
data = {
|
||||||
'sign': str(date_time)
|
'sign': str(date_time),
|
||||||
|
'm_num': str(m_num)
|
||||||
}
|
}
|
||||||
req = requests.post(self.sign_url, data=data)
|
req = requests.post(self.sign_url, data=data)
|
||||||
sign = req.text
|
sign = req.text
|
||||||
return sign
|
return sign
|
||||||
|
|
||||||
def get_task(self, i, time_str):
|
def get_task(self, i, time_str, m_num):
|
||||||
m = self.get_sign(time_str)
|
m = self.get_sign(time_str, m_num) + '; path=/'
|
||||||
print(m)
|
|
||||||
url = f"https://match.yuanrenxue.cn/api/match/9?page={i}"
|
url = f"https://match.yuanrenxue.cn/api/match/9?page={i}"
|
||||||
Headers = {
|
Headers = {
|
||||||
"User-Agent": "yuanrenxue.project",
|
"User-Agent": "yuanrenxue.project",
|
||||||
'Cookie': f'm={m}; sessionid=t9dlfwn9s4ed4z1w1sktxg3k55dc3ko6'
|
'Cookie': f'{m}; sessionid=t9dlfwn9s4ed4z1w1sktxg3k55dc3ko6'
|
||||||
}
|
}
|
||||||
req = requests.get(url, headers=Headers)
|
req = requests.get(url, headers=Headers)
|
||||||
return req.text
|
return req.text
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
time_str = self.get_decrypt()
|
for i in range(1, 6):
|
||||||
for i in range(2, 6):
|
time_str, m_num = self.get_decrypt()
|
||||||
res_dict = json.loads(self.get_task(i, time_str))
|
res_dict = json.loads(self.get_task(i, time_str, m_num))
|
||||||
print(res_dict)
|
print(res_dict)
|
||||||
for j in res_dict.get('data'):
|
for j in res_dict.get('data'):
|
||||||
self.sum_value += j.get('value')
|
self.sum_value += j.get('value')
|
||||||
print(self.sum_value)
|
print(self.sum_value / 50)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -8,8 +8,9 @@ app.use(bodyParser());
|
|||||||
app.post('/get_sign', function (req, res) {
|
app.post('/get_sign', function (req, res) {
|
||||||
let result = req.body;
|
let result = req.body;
|
||||||
let sign = result.sign;
|
let sign = result.sign;
|
||||||
|
let m_num = result.m_num;
|
||||||
console.log(sign);
|
console.log(sign);
|
||||||
result = encryption.get_m(sign);
|
result = encryption.get_m(sign, m_num);
|
||||||
res.send(result.toString());
|
res.send(result.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
|