猿人学第9题js混淆-动态cookie2
@ -1,5 +1,83 @@
|
||||
# 猿人学第9题js混淆-动态cookie2
|
||||
|
||||
## 找到cookie加密点
|
||||
先用油猴插件hook如下
|
||||
|
||||

|
||||
|
||||
这里就找到了cookie设置的位置
|
||||
|
||||

|
||||
|
||||
源代码:
|
||||
```javascript
|
||||
document[$b('\x30\x78\x31\x33\x31', '\x4d\x45\x47\x72') + $b('\x30\x78\x34\x37', '\x73\x5d\x34\x47')] = f[$b('\x30\x78\x38\x30', '\x4c\x61\x25\x6c') + '\x5a\x79'](f[$b('\x30\x78\x31\x33\x34', '\x6f\x63\x67\x33') + '\x4c\x45']('\x6d\x3d', f['\x4d\x72\x56' + '\x52\x70'](m, 0x1)[$b('\x30\x78\x31\x30\x38', '\x2a\x46\x4b\x62') + $b('\x30\x78\x38\x64', '\x6a\x39\x52\x61') + '\x6e\x67']()), res) + f['\x63\x79\x66' + '\x57\x56'];
|
||||
```
|
||||
|
||||
修改后
|
||||
```javascript
|
||||
document['cookie'] = 'm=' + '2' + res + '; path=/';
|
||||
```
|
||||
|
||||

|
||||
|
||||
这里的`res`就是要得到的关键值cookie。
|
||||
|
||||
继续向上找:
|
||||
|
||||

|
||||
|
||||
```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');
|
||||
```
|
||||
|
||||
修改后
|
||||
```javascript
|
||||
res = decrypt('1693276453') + 'r';
|
||||
```
|
||||
|
||||
通过控制台可以看出函数`decrypt`是udc.js文件生成的。
|
||||
|
||||
继续进入,打上断点,可以看到这样一段代码
|
||||
```javascript
|
||||
function _0x4f6d79(_0x50f9fa) {
|
||||
var _0x4e9298 = {
|
||||
'rolMp': _0x56ae('0xdfb', '\x5a\x21\x4a\x24')
|
||||
};
|
||||
const _0x506402 = _0x4e9298['\x72\x6f\x6c\x4d\x70'];
|
||||
const _0xc7daa3 = new JSEncrypt();
|
||||
_0xc7daa3[_0x56ae('0xdfc', '\x72\x4f\x64\x30')](_0x506402);
|
||||
return encodeURIComponent(_0xc7daa3[_0x56ae('0xdfd', '\x24\x58\x44\x69')](_0x50f9fa));
|
||||
}
|
||||
```
|
||||
经过调试发现传入的值`_0x50f9fa`就是`decrypt('1693276453')`传入的字符串时间戳
|
||||
|
||||

|
||||
|
||||
目前还原后的代码就是
|
||||
```javascript
|
||||
function decrypt(_0x50f9fa) {
|
||||
const _0x506402 = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5GVku07yXCndaMS1evPIPyWwhbdWMVRqL4qg4OsKbzyTGmV4YkG8H0hwwrFLuPhqC5tL136aaizuL/lN5DRRbePct6syILOLLCBJ5J5rQyGr00l1zQvdNKYp4tT5EFlqw8tlPkibcsd5Ecc8sTYa77HxNeIa6DRuObC5H9t85ALJyDVZC3Y4ES/u61Q7LDnB3kG9MnXJsJiQxm1pLkE7Zfxy29d5JaXbbfwhCDSjE4+dUQoq2MVIt2qVjZSo5Hd/bAFGU1Lmc7GkFeLiLjNTOfECF52ms/dks92Wx/glfRuK4h/fcxtGB4Q2VXu5k68e/2uojs6jnFsMKVe+FVUDkQIDAQAB';
|
||||
const _0xc7daa3 = new JSEncrypt();
|
||||
_0xc7daa3['setPublicKey'](_0x506402);
|
||||
return encodeURIComponent(_0xc7daa3['encrypt'](_0x50f9fa));
|
||||
}
|
||||
|
||||
res = decrypt('1693276453') + 'r';
|
||||
|
||||
document = {};
|
||||
document['cookie'] = 'm=' + '2' + res + '; path=/';
|
||||
console.log(document);
|
||||
```
|
||||
|
||||
## 找出`JSEncrypt`加密生成逻辑
|
||||
|
||||
先将`udc.js`中的代码,用`v_jstools`进行16进制转成10进制,全局搜索就找到`JSEncrypt`赋值点,
|
||||
|
||||

|
||||
|
||||
`JSEncrypt`是通过_0x4b4d2c生成的
|
||||
|
||||
## 去除格式化检测代码
|
||||
|
||||
第一处
|
||||
@ -69,4 +147,24 @@ _0x569c5b.prototype.checkState = function() {
|
||||
return this.runState(_0x225f13.test(this.newState.toString()) ? --this.states[1] : --this.states[0]);
|
||||
}
|
||||
```
|
||||
再次运行报错`Maximum call stack size exceeded`
|
||||
再次运行报错`Maximum call stack size exceeded`
|
||||
|
||||
## AST还原简单的`CallExpression`类型
|
||||
|
||||
如何将下面的代码:
|
||||
```javascript
|
||||
var Xor = function (p,q)
|
||||
{
|
||||
return p ^ q;
|
||||
}
|
||||
let a = Xor(111,222);
|
||||
```
|
||||
转变成下面的:
|
||||
```javascript
|
||||
var Xor = function (p,q)
|
||||
{
|
||||
return p ^ q;
|
||||
}
|
||||
let a = 111 ^ 222;
|
||||
```
|
||||
分析:上面的转变其实就是将 Xor(111,222) 变成 111 ^ 222
|
@ -3857,24 +3857,32 @@ var _0x56ae = function (_0x4f4e67, _0x43c602) {
|
||||
return _0x223635;
|
||||
};
|
||||
|
||||
console.log(_0x56ae("0x0", "TBzU"))
|
||||
// console.log(_0x56ae("0x0", "TBzU"));
|
||||
|
||||
const replaceArrayElements =
|
||||
const callToLiteral =
|
||||
{
|
||||
MemberExpression: {
|
||||
exit(path) {
|
||||
let {object, property} = path.node;
|
||||
if (!types.isIdentifier(object, {name: __0x9a4eb}) ||
|
||||
!types.isNumericLiteral(property)) {
|
||||
return;
|
||||
}
|
||||
let value = eval(path.toString());
|
||||
path.replaceWith(types.valueToNode(value));
|
||||
CallExpression(path) {
|
||||
// 拿到callee节点和arguments节点
|
||||
let {callee, arguments} = path.node;
|
||||
// 判断callee的节点类型 和 判断arguments是否只有2个参数
|
||||
if (!types.isIdentifier(callee) || arguments.length != 2) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
}
|
||||
// 获得函数名
|
||||
let name = callee.name;
|
||||
// 检查数组是否包含变量 name 的值
|
||||
// 判断数组中第一个元素的类型是否是StringLiteral
|
||||
if (!['_0x56ae'].includes(name) || !types.isStringLiteral(arguments[0])) {
|
||||
return 0;
|
||||
}
|
||||
// 获取NumericLiteral的值
|
||||
let value = _0x56ae(arguments[0].value, arguments[1].value);
|
||||
// 替换节点值
|
||||
path.replaceWith(types.valueToNode(value));
|
||||
}
|
||||
};
|
||||
|
||||
traverse(ast, replaceArrayElements);
|
||||
traverse(ast, callToLiteral);
|
||||
|
||||
let {code} = generator(ast, opts = {jsescOption: {"minimal": true}});
|
||||
|
||||
|
27
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/ast_1.js
Normal file
@ -0,0 +1,27 @@
|
||||
const fs = require('fs');
|
||||
const parser = require("@babel/parser");
|
||||
const traverse = require("@babel/traverse").default;
|
||||
const types = require("@babel/types");
|
||||
const generator = require("@babel/generator").default;
|
||||
|
||||
// 元代码
|
||||
process.argv.length > 2 ? encodeFile = process.argv[2] : encodeFile = "./encode.js";
|
||||
// 被重新编译后的代码
|
||||
process.argv.length > 3 ? decodeFile = process.argv[3] : decodeFile = "./decodeResult.js";
|
||||
|
||||
let sourceCode = fs.readFileSync(encodeFile, {encoding: "utf-8"});
|
||||
let ast = parser.parse(sourceCode);
|
||||
|
||||
const callToLiteral =
|
||||
{
|
||||
Call2Expression(path) {
|
||||
console.log(path)
|
||||
}
|
||||
};
|
||||
|
||||
traverse(ast, callToLiteral);
|
||||
|
||||
let {code} = generator(ast, opts = {jsescOption: {"minimal": true}});
|
||||
|
||||
fs.writeFile(decodeFile, code, (err) => {
|
||||
});
|
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/1.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/2.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/3.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/4.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/5.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/6.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
猿人学Web端爬虫攻防刷题平台/猿人学第9题js混淆-动态cookie2/img/7.png
Normal file
After Width: | Height: | Size: 24 KiB |