猿人学第九题反混淆

fiddler定位到cookie m。

通过hook cookie

定位到:

document[$b('\x30\x78\x36\x34', '\x47\x4e\x47\x28') + $b('\x30\x78\x64\x37', '\x64\x73\x5e\x52')] = f[$b('\x30\x78\x66\x66', '\x47\x28\x6a\x44') + '\x48\x75'](f[$b('\x30\x78\x31\x31\x30', '\x64\x37\x37\x42') + '\x48\x75']('\x6d\x3d', f['\x4c\x4a\x78' + '\x44\x57'](m, 0x1)[$b('\x30\x78\x31\x32\x36', '\x37\x6a\x34\x62') + $b('\x30\x78\x64\x30', '\x49\x4f\x29\x37') + '\x6e\x67']()), res) + ('\x3b\x20\x70' + $b('\x30\x78\x34\x65', '\x63\x6a\x57\x36') + '\x3d\x2f');
 是赋值的位置。

使用AST:AST explorer

结构很清晰:前3项是数组还原及调用还原。前3项js取出,命名为:9_1_array_revert.js。

后三项取出,命名为9_mid-1.js,并生成对应的json

node JsToJson.js  9_mid-1.js 9_mid-1.json

 需要用到的脚本:

// js 转 json 
const fs = require('fs');
const esprima = require('esprima')
const escodegen = require('escodegen')

const input_text = process.argv[2];
const output_text = process.argv[3];

const data = fs.readFileSync(input_text);
const ast = esprima.parseScript(data.toString());
const ast_to_json = JSON.stringify(ast);
fs.writeFileSync(output_text, ast_to_json);

// json 转 js
const fs = require('fs');
const esprima = require('esprima')
const escodegen = require('escodegen')

const input_text = process.argv[2];
const output_text = process.argv[3];

const data = fs.readFileSync(input_text);
const ast = JSON.parse(data.toString());
const code = escodegen.generate(ast, {
    format: {
        compact: true,
        escapeless: true
    }
});
fs.writeFileSync(output_text, code);

一、大数组还原

直接浏览器中执行,即可得到$a的值,因为有格式化校验,若格式化,需要去除对应的检查,否则会死循环。

$a=['\x4a\x73\x4b\x54\x77\x6f\x34\x3d','\x4e\x32\x37\x43\x75\x77\x3d\x3d','\x77\x6f\x46\x2f\x77\x6f\x63\x3d','\x51\x42\x55\x32','\x77\x72\x74\x76\x77\x36\x59\x3d','\x77\x70\x5a\x4b\x66\x67\x3d\x3d','\x77\x6f\x4c\x43\x6f\x79\x34\x3d','\x77\x71\x46\x52\x64\x41\x3d\x3d','\x46\x55\x7a\x43\x73\x77\x3d\x3d','\x77\x37\x6b\x6f\x59\x67\x3d\x3d','\x4f\x77\x56\x6b','\x77\x72\x34\x71\x63\x77\x3d\x3d','\x4c\x6d\x6e\x44\x76\x41\x3d\x3d','\x77\x35\x6b\x39\x55\x41\x3d\x3d','\x77\x37\x55\x41\x61\x51\x3d\x3d','\x53\x45\x76\x44\x6d\x41\x3d\x3d','\x77\x35\x67\x4a\x4f\x77\x3d\x3d','\x77\x6f\x6f\x35\x77\x72\x30\x3d','\x77\x6f\x46\x78\x77\x36\x49\x3d','\x77\x37\x68\x71\x77\x34\x30\x3d','\x77\x70\x54\x44\x6f\x73\x4b\x68','\x57\x38\x4f\x57\x46\x67\x3d\x3d','\x45\x38\x4f\x6d\x46\x41\x3d\x3d','\x65\x7a\x63\x53','\x77\x34\x59\x72\x77\x37\x45\x3d','\x65\x31\x59\x76','\x77\x70\x67\x56\x77\x71\x6f\x3d','\x77\x34\x34\x7a\x58\x41\x3d\x3d','\x46\x47\x4c\x44\x73\x77\x3d\x3d','\x77\x71\x41\x33\x4f\x51\x3d\x3d','\x77\x70\x58\x44\x67\x4d\x4b\x46','\x55\x73\x4f\x4d\x48\x41\x3d\x3d','\x4b\x63\x4b\x33\x77\x70\x77\x3d','\x4d\x47\x48\x43\x75\x41\x3d\x3d','\x77\x70\x30\x46\x77\x72\x4d\x3d','\x53\x56\x46\x64','\x77\x6f\x64\x65\x4b\x77\x3d\x3d','\x77\x6f\x56\x4d\x66\x51\x3d\x3d','\x77\x6f\x64\x36\x4b\x51\x3d\x3d','\x56\x67\x49\x35','\x77\x70\x44\x44\x6c\x63\x4b\x54','\x4f\x78\x30\x31','\x4e\x77\x74\x79','\x77\x70\x62\x43\x67\x30\x73\x3d','\x77\x71\x6e\x43\x67\x4d\x4f\x64','\x44\x46\x73\x61','\x59\x57\x55\x31','\x77\x35\x38\x64\x77\x35\x67\x3d','\x77\x6f\x6e\x44\x69\x63\x4b\x79','\x77\x35\x30\x74\x41\x51\x3d\x3d','\x50\x63\x4b\x6f\x77\x6f\x30\x3d','\x77\x70\x64\x64\x66\x67\x3d\x3d','\x55\x47\x77\x69','\x77\x70\x33\x43\x67\x45\x73\x3d','\x77\x6f\x35\x45\x64\x77\x3d\x3d','\x4e\x77\x51\x71','\x77\x36\x6b\x45\x66\x77\x3d\x3d','\x49\x44\x30\x52','\x77\x37\x78\x45\x77\x37\x77\x3d','\x42\x4d\x4f\x36\x5a\x51\x3d\x3d','\x77\x35\x77\x62\x77\x37\x34\x3d','\x57\x33\x38\x35','\x77\x35\x67\x53\x50\x41\x3d\x3d','\x77\x34\x73\x64\x77\x6f\x73\x3d','\x77\x6f\x73\x55\x77\x72\x55\x3d','\x77\x37\x51\x5a\x77\x34\x51\x3d','\x43\x41\x7a\x43\x6b\x41\x3d\x3d','\x49\x42\x66\x43\x74\x67\x3d\x3d','\x77\x6f\x52\x4f\x77\x37\x67\x3d','\x42\x44\x34\x75','\x4f\x46\x30\x66','\x44\x63\x4b\x34\x54\x41\x3d\x3d','\x46\x38\x4b\x41\x77\x71\x6f\x3d','\x50\x7a\x30\x61','\x62\x46\x2f\x44\x6a\x41\x3d\x3d','\x4a\x4d\x4b\x36\x77\x72\x51\x3d','\x77\x34\x73\x68\x56\x51\x3d\x3d','\x62\x46\x42\x54','\x4f\x38\x4b\x70\x77\x36\x51\x3d','\x5a\x55\x6f\x5a','\x42\x73\x4b\x78\x77\x72\x6b\x3d','\x57\x32\x30\x63','\x77\x6f\x66\x43\x73\x73\x4f\x72','\x77\x36\x67\x68\x45\x67\x3d\x3d','\x77\x71\x7a\x44\x75\x63\x4b\x65','\x77\x72\x66\x43\x6a\x4d\x4f\x43','\x45\x4d\x4b\x66\x77\x70\x77\x3d','\x56\x4d\x4f\x56\x48\x67\x3d\x3d','\x41\x6d\x44\x44\x71\x77\x3d\x3d','\x77\x36\x70\x6f\x4d\x77\x3d\x3d','\x77\x71\x58\x44\x73\x68\x51\x3d','\x77\x36\x51\x47\x5a\x67\x3d\x3d','\x77\x34\x31\x30\x43\x67\x3d\x3d','\x77\x70\x52\x65\x57\x67\x3d\x3d','\x45\x57\x66\x43\x72\x51\x3d\x3d','\x50\x73\x4b\x77\x77\x37\x6f\x3d','\x61\x58\x73\x57','\x77\x6f\x67\x74\x45\x41\x3d\x3d','\x77\x71\x78\x66\x77\x71\x77\x3d','\x77\x34\x48\x43\x6d\x42\x63\x3d','\x77\x36\x48\x43\x6a\x63\x4b\x4d','\x58\x51\x45\x66','\x77\x37\x6c\x4c\x4f\x67\x3d\x3d','\x77\x36\x48\x43\x67\x44\x63\x3d','\x77\x36\x78\x43\x77\x36\x73\x3d','\x43\x4d\x4b\x66\x77\x36\x59\x3d','\x77\x72\x72\x44\x69\x68\x67\x3d','\x51\x4d\x4b\x74\x64\x41\x3d\x3d','\x61\x6d\x68\x41','\x77\x36\x2f\x43\x6e\x79\x73\x3d','\x5a\x55\x44\x44\x68\x51\x3d\x3d','\x77\x35\x34\x7a\x58\x67\x3d\x3d','\x77\x36\x78\x51\x77\x36\x73\x3d','\x77\x71\x67\x31\x61\x77\x3d\x3d','\x48\x6d\x33\x44\x74\x67\x3d\x3d','\x45\x4d\x4b\x46\x77\x35\x6f\x3d','\x4b\x4d\x4b\x66\x77\x34\x6b\x3d','\x4f\x73\x4b\x45\x77\x6f\x41\x3d','\x55\x30\x6a\x44\x6a\x77\x3d\x3d','\x77\x71\x7a\x44\x75\x63\x4b\x2b','\x77\x72\x70\x4a\x77\x34\x6b\x3d','\x77\x36\x72\x43\x70\x38\x4f\x54','\x77\x37\x6a\x43\x76\x73\x4f\x43','\x77\x70\x76\x44\x6f\x41\x38\x3d','\x77\x6f\x46\x59\x77\x37\x34\x3d','\x4c\x6e\x44\x44\x72\x67\x3d\x3d','\x77\x6f\x74\x31\x77\x36\x49\x3d','\x77\x70\x4c\x43\x73\x63\x4f\x63','\x55\x6c\x37\x44\x67\x77\x3d\x3d','\x49\x53\x39\x42','\x77\x71\x31\x50\x45\x77\x3d\x3d','\x63\x73\x4f\x6b\x4e\x77\x3d\x3d','\x44\x67\x33\x43\x70\x77\x3d\x3d','\x62\x55\x5a\x33','\x77\x35\x68\x31\x46\x67\x3d\x3d','\x77\x35\x77\x62\x77\x34\x67\x3d','\x77\x37\x68\x4c\x44\x77\x3d\x3d','\x4f\x54\x77\x56','\x56\x79\x6a\x43\x76\x77\x3d\x3d','\x44\x6c\x64\x32','\x77\x34\x54\x43\x6c\x63\x4f\x68','\x41\x6e\x58\x44\x71\x41\x3d\x3d','\x77\x6f\x73\x6c\x77\x35\x59\x3d','\x77\x70\x6e\x44\x73\x54\x51\x3d','\x57\x73\x4f\x65\x58\x67\x3d\x3d','\x77\x34\x73\x41\x77\x35\x6f\x3d','\x48\x57\x39\x76','\x77\x70\x2f\x43\x6a\x63\x4b\x78','\x47\x41\x6a\x43\x6b\x41\x3d\x3d','\x77\x36\x4e\x5a\x77\x36\x63\x3d','\x77\x36\x72\x44\x70\x4d\x4f\x45','\x77\x35\x58\x44\x67\x79\x6f\x3d','\x4d\x78\x35\x6b','\x77\x35\x4d\x66\x77\x71\x55\x3d','\x77\x70\x66\x44\x6e\x63\x4b\x73','\x42\x47\x7a\x44\x73\x77\x3d\x3d','\x77\x71\x74\x68\x56\x51\x3d\x3d','\x77\x37\x58\x44\x6d\x73\x4b\x55','\x77\x37\x67\x55\x77\x36\x63\x3d','\x4a\x6b\x66\x44\x6e\x77\x3d\x3d','\x56\x46\x4c\x44\x69\x41\x3d\x3d','\x43\x4d\x4b\x43\x77\x70\x6f\x3d','\x43\x6c\x2f\x43\x6f\x41\x3d\x3d','\x77\x70\x42\x73\x77\x36\x77\x3d','\x56\x78\x51\x39','\x47\x73\x4b\x4b\x77\x71\x34\x3d','\x64\x52\x67\x2f','\x4e\x6b\x49\x6a','\x77\x36\x35\x52\x77\x37\x63\x3d','\x77\x6f\x58\x44\x72\x54\x77\x3d','\x77\x72\x6c\x50\x49\x67\x3d\x3d','\x77\x72\x50\x44\x73\x4d\x4b\x50','\x45\x77\x35\x72','\x63\x56\x45\x67','\x48\x41\x76\x43\x6f\x51\x3d\x3d','\x77\x71\x44\x44\x68\x73\x4b\x65','\x77\x36\x6e\x44\x6d\x73\x4f\x50','\x77\x34\x77\x73\x51\x67\x3d\x3d','\x49\x33\x6c\x49','\x48\x6a\x62\x43\x6a\x41\x3d\x3d','\x61\x6e\x67\x4c','\x77\x37\x33\x43\x6b\x53\x34\x3d','\x77\x36\x55\x74\x77\x70\x38\x3d','\x57\x6d\x63\x50','\x77\x72\x63\x77\x4e\x67\x3d\x3d','\x77\x36\x50\x43\x6a\x4d\x4f\x43','\x77\x72\x48\x44\x6b\x6a\x30\x3d','\x77\x34\x2f\x43\x6f\x52\x49\x3d','\x77\x70\x49\x53\x77\x70\x34\x3d','\x77\x72\x76\x44\x74\x38\x4b\x52','\x54\x63\x4f\x73\x49\x51\x3d\x3d','\x77\x34\x55\x6d\x52\x41\x3d\x3d','\x51\x73\x4f\x4d\x48\x67\x3d\x3d','\x77\x36\x44\x44\x69\x38\x4b\x50','\x4a\x38\x4f\x44\x64\x41\x3d\x3d','\x77\x36\x2f\x44\x76\x63\x4b\x4d','\x54\x47\x7a\x44\x6a\x77\x3d\x3d','\x44\x63\x4b\x38\x77\x71\x4d\x3d','\x43\x7a\x62\x44\x6f\x77\x3d\x3d','\x77\x36\x34\x4f\x51\x41\x3d\x3d','\x77\x6f\x45\x57\x58\x51\x3d\x3d','\x77\x72\x77\x77\x77\x72\x51\x3d','\x77\x35\x30\x44\x59\x67\x3d\x3d','\x77\x72\x4a\x65\x4d\x67\x3d\x3d','\x77\x70\x6a\x44\x68\x77\x73\x3d','\x77\x72\x6b\x6c\x77\x6f\x38\x3d','\x61\x79\x5a\x66','\x77\x36\x77\x78\x65\x77\x3d\x3d','\x43\x4d\x4f\x6d\x5a\x77\x3d\x3d','\x52\x4d\x4b\x49\x4e\x67\x3d\x3d','\x77\x35\x6b\x75\x55\x77\x3d\x3d','\x77\x70\x39\x64\x77\x70\x6b\x3d','\x77\x71\x66\x43\x6f\x73\x4f\x37','\x77\x72\x56\x53\x77\x37\x38\x3d','\x77\x72\x51\x34\x62\x67\x3d\x3d','\x59\x6c\x59\x67','\x77\x71\x37\x44\x69\x38\x4f\x4b','\x64\x32\x44\x44\x74\x77\x3d\x3d','\x47\x52\x2f\x43\x67\x41\x3d\x3d','\x77\x35\x77\x64\x77\x35\x55\x3d','\x43\x63\x4f\x78\x64\x77\x3d\x3d','\x48\x33\x39\x4e','\x50\x63\x4b\x52\x77\x71\x55\x3d','\x77\x36\x54\x43\x76\x73\x4f\x54','\x77\x36\x6f\x56\x77\x71\x38\x3d','\x43\x56\x44\x43\x72\x67\x3d\x3d','\x4f\x51\x50\x43\x6d\x67\x3d\x3d','\x77\x70\x55\x49\x77\x72\x73\x3d','\x77\x34\x67\x58\x77\x34\x55\x3d','\x55\x38\x4f\x55\x4c\x77\x3d\x3d','\x5a\x48\x50\x43\x71\x67\x3d\x3d','\x59\x51\x67\x70','\x65\x31\x45\x6a','\x77\x37\x4d\x45\x52\x77\x3d\x3d','\x49\x47\x6a\x44\x68\x67\x3d\x3d','\x77\x34\x67\x4a\x4f\x51\x3d\x3d','\x64\x79\x67\x6e','\x55\x52\x67\x6e','\x77\x34\x56\x51\x77\x6f\x49\x3d','\x77\x6f\x2f\x44\x6b\x6a\x77\x3d','\x77\x70\x6b\x44\x52\x67\x3d\x3d','\x77\x71\x6a\x44\x69\x73\x4b\x45','\x77\x35\x31\x6f\x47\x51\x3d\x3d','\x66\x41\x63\x32','\x58\x31\x39\x52','\x77\x72\x49\x36\x77\x70\x41\x3d','\x77\x35\x6b\x35\x66\x51\x3d\x3d','\x77\x34\x74\x79\x46\x67\x3d\x3d','\x41\x4d\x4b\x45\x77\x37\x77\x3d','\x77\x37\x58\x43\x6e\x38\x4b\x63','\x77\x70\x72\x44\x69\x78\x45\x3d','\x77\x6f\x63\x6d\x4e\x77\x3d\x3d','\x56\x63\x4f\x47\x41\x77\x3d\x3d','\x77\x36\x38\x54\x63\x67\x3d\x3d','\x59\x6c\x41\x46','\x4c\x51\x38\x6a','\x77\x71\x66\x43\x6a\x4d\x4f\x41','\x53\x44\x34\x50','\x77\x72\x58\x43\x71\x73\x4f\x6b','\x77\x37\x67\x62\x56\x51\x3d\x3d','\x61\x41\x39\x63','\x57\x6a\x78\x61','\x77\x6f\x46\x51\x77\x36\x41\x3d','\x77\x36\x4c\x44\x6b\x4d\x4b\x4a','\x59\x44\x51\x65','\x4d\x45\x48\x44\x6e\x77\x3d\x3d','\x77\x71\x63\x7a\x77\x70\x41\x3d','\x44\x38\x4b\x35\x77\x70\x77\x3d','\x65\x78\x68\x2f','\x46\x38\x4f\x66\x52\x41\x3d\x3d','\x77\x36\x33\x44\x69\x42\x4d\x3d','\x65\x31\x45\x67','\x41\x4d\x4f\x45\x77\x6f\x63\x3d','\x77\x34\x77\x64\x77\x35\x63\x3d','\x77\x35\x6b\x7a\x59\x51\x3d\x3d','\x77\x36\x6e\x43\x6d\x63\x4f\x76','\x54\x32\x68\x63','\x66\x31\x64\x35','\x77\x36\x6b\x45\x5a\x41\x3d\x3d','\x57\x73\x4f\x58\x4c\x77\x3d\x3d','\x44\x46\x46\x6a','\x77\x6f\x64\x59\x77\x37\x6b\x3d','\x77\x35\x6f\x57\x4a\x51\x3d\x3d','\x77\x34\x49\x31\x77\x36\x45\x3d','\x48\x4d\x4b\x62\x63\x51\x3d\x3d','\x64\x30\x78\x6d','\x45\x41\x6a\x43\x6e\x41\x3d\x3d','\x59\x73\x4b\x51\x77\x71\x34\x3d','\x5a\x73\x4b\x36\x77\x35\x73\x3d','\x5a\x6a\x73\x41','\x77\x36\x46\x57\x77\x37\x38\x3d','\x77\x35\x74\x77\x44\x41\x3d\x3d','\x48\x32\x6e\x44\x75\x67\x3d\x3d','\x77\x37\x6b\x66\x59\x77\x3d\x3d','\x77\x6f\x72\x44\x6b\x63\x4b\x37','\x53\x6b\x76\x44\x6e\x51\x3d\x3d','\x56\x63\x4f\x79\x4b\x77\x3d\x3d','\x77\x6f\x72\x43\x70\x63\x4f\x6b','\x4d\x41\x4d\x78','\x77\x35\x55\x32\x77\x37\x77\x3d','\x77\x37\x62\x43\x6e\x63\x4f\x61','\x77\x36\x7a\x44\x6e\x38\x4b\x72','\x77\x36\x45\x62\x41\x67\x3d\x3d','\x77\x71\x6f\x73\x47\x41\x3d\x3d','\x77\x72\x51\x53\x77\x72\x55\x3d','\x50\x63\x4b\x68\x61\x67\x3d\x3d','\x77\x72\x51\x34\x77\x6f\x59\x3d','\x77\x72\x59\x78\x77\x72\x77\x3d','\x77\x37\x77\x73\x4a\x51\x3d\x3d','\x66\x48\x46\x6e','\x77\x72\x4c\x44\x69\x73\x4b\x47','\x77\x36\x33\x44\x69\x4d\x4b\x48','\x4e\x52\x7a\x43\x76\x41\x3d\x3d','\x77\x34\x34\x79\x64\x41\x3d\x3d','\x4e\x31\x48\x43\x6c\x41\x3d\x3d','\x77\x37\x34\x44\x65\x41\x3d\x3d','\x77\x37\x58\x44\x6c\x38\x4b\x4f','\x62\x56\x30\x36','\x44\x58\x46\x50','\x77\x35\x34\x65\x4e\x67\x3d\x3d','\x77\x71\x4c\x44\x69\x73\x4b\x45','\x64\x4d\x4f\x6b\x4f\x77\x3d\x3d','\x4e\x32\x66\x43\x75\x77\x3d\x3d','\x47\x31\x37\x43\x70\x77\x3d\x3d','\x77\x70\x76\x44\x71\x63\x4b\x77','\x4e\x38\x4b\x70\x77\x6f\x55\x3d','\x77\x70\x4d\x57\x77\x70\x41\x3d','\x62\x46\x63\x68','\x77\x70\x44\x44\x72\x73\x4b\x2b','\x77\x71\x76\x43\x74\x63\x4f\x42','\x43\x63\x4b\x54\x77\x6f\x38\x3d','\x55\x78\x6b\x78','\x49\x7a\x4d\x4f','\x45\x41\x4c\x43\x6c\x51\x3d\x3d','\x77\x70\x4c\x44\x6e\x73\x4b\x78','\x77\x70\x6e\x44\x6f\x52\x77\x3d','\x77\x35\x6a\x44\x72\x38\x4b\x73','\x77\x34\x45\x54\x4d\x77\x3d\x3d','\x77\x71\x52\x44\x4c\x41\x3d\x3d','\x77\x70\x41\x39\x43\x77\x3d\x3d','\x44\x41\x6e\x43\x75\x77\x3d\x3d','\x4c\x38\x4b\x46\x63\x77\x3d\x3d','\x63\x6e\x33\x44\x6b\x51\x3d\x3d','\x4d\x32\x6e\x43\x70\x51\x3d\x3d','\x77\x70\x38\x4b\x43\x77\x3d\x3d','\x77\x71\x70\x75\x56\x77\x3d\x3d','\x44\x41\x4a\x42','\x50\x4d\x4b\x68\x77\x6f\x34\x3d','\x5a\x54\x55\x66','\x51\x68\x34\x4a','\x4b\x63\x4b\x6b\x77\x37\x38\x3d','\x4c\x4d\x4b\x54\x77\x6f\x4d\x3d','\x77\x34\x31\x76\x46\x41\x3d\x3d','\x49\x63\x4b\x6c\x77\x70\x38\x3d','\x42\x48\x62\x44\x68\x67\x3d\x3d','\x77\x36\x2f\x44\x6b\x73\x4b\x51','\x55\x68\x34\x6e','\x77\x35\x54\x44\x68\x51\x49\x3d','\x77\x71\x49\x68\x77\x70\x38\x3d','\x77\x37\x6a\x44\x72\x4d\x4b\x39','\x4e\x43\x4c\x44\x76\x77\x3d\x3d','\x50\x47\x4e\x6b','\x77\x34\x34\x71\x58\x41\x3d\x3d','\x4c\x46\x54\x43\x6a\x51\x3d\x3d','\x77\x36\x68\x58\x77\x36\x73\x3d','\x77\x72\x59\x74\x77\x70\x49\x3d','\x4b\x4d\x4f\x36\x66\x51\x3d\x3d'];(function(a,b){var c=function(g){while(--g){a['push'](a['shift']());}};var f=function(){var g={'data':{'key':'cookie','value':'timeout'},'setCookie':function(k,l,m,n){n=n||{};var o=l+'='+m;var p=0x0;for(var q=0x0,r=k['length'];q<r;q++){var s=k[q];o+=';\x20'+s;var t=k[s];k['push'](t);r=k['length'];if(t!==!![]){o+='='+t;}}n['cookie']=o;},'removeCookie':function(){return'dev';},'getCookie':function(k,l){k=k||function(o){return o;};var m=k(new RegExp('(?:^|;\x20)'+l['replace'](/([.$?*|{}()[]\/+^])/g,'$1')+'=([^;]*)'));var n=function(o,p){o(++p);};n(c,b);return m?decodeURIComponent(m[0x1]):undefined;}};var h=function(){var k=new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');return k['test'](g['removeCookie']['toString']());};g['updateCookie']=h;var i='';var j=g['updateCookie']();if(!j){g['setCookie'](['*'],'counter',0x1);}else if(j){i=g['getCookie'](null,'counter');}else{g['removeCookie']();}};f();}($a,0x133));

二、函数还原

执行函数还原前,大数组还原不是必须的。但是大数组还原后可以大幅提升还原函数的速

度。

import json
import os

import execjs


def call_function_reload(node, ctx):
    # 从根遍历节点
    if type(node) == list:
        for item in node:
            call_function_reload(item, ctx)
        return
    elif type(node) != dict:
        return
    # 捕获一个 CallExpression 节点
    if node['type'] == 'CallExpression':
        try:
            if node['callee']['name'] == '$b':
                arg_list = []
                for item in node['arguments']:
                    if item['type'] != 'Literal':
                        break
                    arg_list.append(item['value'])  # 提取参数
                value = ctx.call('$b', *arg_list)
                print(value)
                new_node = {'type': 'Literal', 'value': value}
                node.clear()
                node.update(new_node)
                return
        except KeyError:
            pass
    for key in node.keys():
        call_function_reload(node[key], ctx)


if __name__ == '__main__':
    with open('9_mid-1.json', 'r', encoding='utf8') as f:
        data = json.loads(f.read())
    # 可先还原大数组,提升替换速度
    with open('9_1_array_revert.js', 'r', encoding='utf-8') as f:
        ctx = execjs.compile(f.read())
    call_function_reload(data, ctx)
    with open('9_mid2.json', 'w', encoding='utf8') as f:
        f.write(json.dumps(data))
    os.system('node JsonToJs 9_mid2.json 9_mid2.js')

 还原前后对比

三、字符串拼接

还原前后效果对比:

 代码如下:

import json
import os


def concat_obj_property_name(node):
    if type(node) == list:
        for item in node:
            concat_obj_property_name(item)
        return
    elif type(node) != dict:
        return
    # 捕获一个二元运算节点
    if node['type'] == 'BinaryExpression':
        if not (node['left']['type'] == 'Literal' and node['right']['type'] == 'Literal'):
            concat_obj_property_name(node['left'])
            concat_obj_property_name(node['right'])
        if node['left']['type'] == 'Literal' and node['right']['type'] == 'Literal':
            # 构造新节点
            new_node = {'type': 'Literal', 'value': node['left']['value'] + node['right']['value']}
            node.clear()
            node.update(new_node)
            return
    for key in node.keys():
        concat_obj_property_name(node[key])


if __name__ == '__main__':
    with open('9_mid2.json', 'r', encoding='utf8') as f:
        data = json.loads(f.read())
    concat_obj_property_name(data)
    with open('9_mid3.json', 'w', encoding='utf8') as f:
        f.write(json.dumps(data))
    os.system('node JsonToJs 9_mid3.json 9_mid3.js')

经过以上三步,已经可以清晰得到cookie赋值的语句了:

  document['cookie'] = f['DWYaI'](f['DWYaI']('m=', f['MsLEj'](m, 1)['toString']()), res);

经过一番处理:

重点就是decrypt 函数

cookie = 'm=2' + decrypt('1676447902') + 'r';

udc.js处理:

同样udc.js也是ob混淆,也许使用AST反混淆,当然硬扣也行。和上述步骤一样,大数组还原单独成一个文件 udc_array_revert.js(方便调用)。

剩余部分保存为udc.js。同样需生成一个udc.json文件。(也可使用babel+traverse+generator+types反混淆,但我个人更喜欢以json形式处理)。

一、函数还原

还原前后对比

import json
import os

import execjs


def call_function_reload(node, ctx):
    # 从根遍历节点
    try:
        if type(node) == list:
            for item in node:
                call_function_reload(item, ctx)
            return
        elif type(node) != dict:
            return
    except Exception as e:
        print(f'error->{e}')
    # 捕获一个 CallExpression 节点
    try:
        if node['type'] == 'CallExpression':
            if node['callee']['name'] == '_0x56ae':
                arg_list = []
                for item in node['arguments']:
                    if item['type'] != 'Literal':
                        break
                    arg_list.append(item['value'])  # 提取参数
                value = ctx.call('_0x56ae', *arg_list)
                print(value)
                new_node = {'type': 'Literal', 'value': value}
                node.clear()
                node.update(new_node)
                return
    except Exception:
        pass
    for key in node.keys():
        call_function_reload(node[key], ctx)


if __name__ == '__main__':
    # 可先还原大数组,提升替换速度
    with open('udc.json', 'r', encoding='utf8') as f:
        data = json.loads(f.read())
    with open('udc_array_reload.js', 'r', encoding='utf-8') as f:
        ctx = execjs.compile(f.read())
    call_function_reload(data, ctx)
    with open('udc_mid1.json', 'w', encoding='utf8') as f:
        f.write(json.dumps(data))
    os.system('node JsonToJs udc_mid1.json udc_mid1.js')

二、对象调用还原

import copy
import json
import os

obj_property_dict = {}
obj_name_list = []


def get_property_dict(node):
    if type(node) == list:
        for item in node:
            get_property_dict(item)
        return
    elif type(node) != dict:
        return
    # 捕获一个表达式序列
    try:
        if node and node['type'] == 'VariableDeclaration':
            for i in node['declarations']:
                if i['type'] == 'VariableDeclarator' and i['init'] and \
                        i['init']['type'] == 'ObjectExpression':
                    if i['id']['name'] not in obj_property_dict:
                        obj_property_dict[i['id']['name']] = {}
                    for j in i['init']['properties']:
                        obj_property_dict[i['id']['name']][j['key']['value']] = j['value']
                    # i.clear()
                    # i.update({"type": 'EmptyStatement'})
    except KeyError as e:
        pass
    for key in node.keys():
        get_property_dict(node[key])


# 对象调用还原
def obj_property_reload(node):
    if type(node) == list:
        for item in node:
            obj_property_reload(item)
        return
    elif type(node) != dict:
        return
    # 捕获一个属性调用节点
    try:
        if node['type'] == 'MemberExpression':
            # 处理形似:_0x5243e3['UhBgk']
            obj_name = node['object']['name']
            obj_property = node['property']['value']
            new_node = obj_property_dict[obj_name][obj_property]
            if new_node['type'] != 'FunctionExpression':
                node.clear()
                node.update(new_node)
                obj_property_reload(node)
    except KeyError:
        pass

    try:
        # 捕获一个函数调用节点,且子节点callee的类型是一个MemberExpression
        if node['type'] != 'CallExpression' or node['callee']['type'] != 'MemberExpression':
            raise KeyError
        obj_name = node['callee']['object']['name']  # 获取对象名称
        obj_property_name = node['callee']['property']['value']  # 获取需要调用的对象属性名称
        function_node = obj_property_dict[obj_name][obj_property_name]  # 获取函数定义节点,即对象的属性值(该属性值是一个函数定义)
    except KeyError:
        for key in node.keys():
            obj_property_reload(node[key])
        return

    # 获取形参
    param_list = [item['name'] for item in function_node['params']]
    # 获取实参
    argument_list = node['arguments']
    try:
        for k in argument_list:
            if k['name'] == 'define' or k['name'] == 'exports':
                return
    except Exception:
        pass
    # 形成形参与实参的对比关系,如此,可以适应形参位置发生变化
    param_argument_dict = dict(zip(param_list, argument_list))
    # 拷贝一份函数节点的返回值子节点
    return_node = copy.deepcopy(function_node['body']['body'][0])
    # print(return_node)
    if return_node['type'] == 'FunctionExpression' and not node['id']:
        print(f'意料之外的函数节点,拥有超过一行的函数体: {function_node}')
        # for key in node.keys():
        #     obj_property_reload(node[key])
        return
    # 使用实参替换返回值节点中的形参,然后用返回值节点,替换掉整个函数调用node节点
    print(return_node)
    try:
        if return_node['argument']['type'] == 'BinaryExpression' or \
                return_node['argument']['type'] == 'LogicalExpression':
            if return_node['argument']['left']['type'] == 'Identifier':
                return_node['argument']['left'] = param_argument_dict[return_node['argument']['left']['name']]
            if return_node['argument']['right']['type'] == 'Identifier':
                return_node['argument']['right'] = param_argument_dict[return_node['argument']['right']['name']]
            node.clear()
            node.update(return_node['argument'])
        elif return_node['argument']['type'] == 'CallExpression':
            # 处理形似return _0x1debf7['rDkzY'](_0x3106cb, _0x48a349)
            if return_node['argument']['callee']['type'] != 'MemberExpression':
                function_name = return_node['argument']['callee']['name']
                if function_name in param_argument_dict:
                    return_node['argument']['callee'] = param_argument_dict[function_name]
                for i in range(len(return_node['argument']['arguments'])):
                    if return_node['argument']['arguments'][i]['type'] == 'Identifier':
                        argument_name = return_node['argument']['arguments'][i]['name']
                        return_node['argument']['arguments'][i] = param_argument_dict[argument_name]
            node.clear()
            node.update(return_node['argument'])
        # else:
        #     print(f'意料之外的函数返回值类型: {return_node}')
        #     sys.exit()
        # 替换完成后,将自身继续递归
    except Exception:
        pass
    for key in node.keys():
        obj_property_reload(node[key])


if __name__ == '__main__':
    with open('udc_mid1.json', 'r', encoding='utf8') as f:
        data = json.loads(f.read())
    get_property_dict(data)
    obj_property_reload(data)
    with open('udc_mid2.json', 'w', encoding='utf8') as f:
        f.write(json.dumps(data))
    os.system('node JsonToJs udc_mid2.json udc_mid2.js')

三、分支判断

去除假分支

import json
import os
import sys

operator_dict = {'===': '==', '!==': '!='}


def if_reload(node):
    if type(node) == list:
        for item in node:
            if_reload(item)
        return
    elif type(node) != dict:
        return

    # 捕获一个分支语句节点
    try:
        if node['type'] == 'IfStatement':
            if node['test']['type'] == 'BinaryExpression':
                # 判断分支条件是否可执行
                if node['test']['left']['type'] == 'Literal' and node['test']['right']['type'] == 'Literal':
                    # 获取分支节点
                    consequent = node['consequent']
                    alternate = node['alternate']
                    try:
                        if eval(f"'{node['test']['left']['value']}' {operator_dict[node['test']['operator']]} '{node['test']['right']['value']}'"):
                            node.clear()
                            node.update(consequent)
                        else:
                            node.clear()
                            node.update(alternate)
                    except KeyError:
                        print(f'意料之外的分支运算符号: {node}')
                        sys.exit()
                    else:
                        if_reload(node)
    except Exception:
        pass
    for key in node.keys():
        if_reload(node[key])


if __name__ == '__main__':
    with open('udc_mid2.json', 'r', encoding='utf8') as f:
        data = json.loads(f.read())
    if_reload(data)

    with open('udc_mid3.json', 'w', encoding='utf8') as f:
        f.write(json.dumps(data))
    os.system('node JsonToJs udc_mid3.json udc_mid3.js')

四、控制流平坦化

import json
import os

obj_property_dict = {}


def get_property_dict(node):
    if type(node) == list:
        for item in node:
            get_property_dict(item)
        return
    elif type(node) != dict:
        return

    # 捕获一个表达式序列
    try:
        if node and node['type'] == 'VariableDeclaration':
            for i in node['declarations']:
                if i['type'] == 'VariableDeclarator' and i['init'] and \
                        i['init']['type'] == 'CallExpression':
                    if i['id']['name'] not in obj_property_dict:
                        obj_property_dict[i['id']['name']] = {}
                    obj_property_dict[i['id']['name']] = i['init']['callee']['object']['value']
                    # i.clear()
                    # i.update({"type": 'EmptyStatement'})
    except KeyError as e:
        pass
    for key in node.keys():
        get_property_dict(node[key])


def sort_code(node):
    if type(node) == list:
        try:
            # 捕获一个控制流节点(这是一个包含执行顺序和while节点的列表节点)
            if len(node) == 2:
                if node[1]['type'] == 'WhileStatement':
                    split_key = node[1]['body']['body'][0]['discriminant']['object']['name']
                    sort_list = obj_property_dict[split_key].split('|')
                    cases_list = node[1]['body']['body'][0]['cases']
                    result_list = [cases_list[int(i)]['consequent'][0] for i in sort_list]
                    node.clear()
                    node.extend(result_list)
            if len(node) == 3:
                if node[2]['type'] == 'WhileStatement':
                    split_key = node[2]['body']['body'][0]['discriminant']['object']['name']
                    sort_list = obj_property_dict[split_key].split('|')  # 控制流程顺序列表
                    cases_list = node[2]['body']['body'][0]['cases']  # 原控制流列表
                    result_list = [cases_list[int(i)]['consequent'][0] for i in sort_list]  # 新的控制流列表
                    node.clear()
                    node.extend(result_list)
        except (KeyError, TypeError):
            for item in node:
                sort_code(item)
            return
    elif type(node) == dict:
        for key in node.keys():
            sort_code(node[key])
        return
    else:
        return

    for item in node:
        sort_code(item)


if __name__ == '__main__':
    with open('udc_mid3.json', 'r', encoding='utf8') as f:
        data = json.loads(f.read())
    get_property_dict(data)
    sort_code(data)
    print(obj_property_dict)
    with open('udc_mid4.json', 'w', encoding='utf8') as f:
        f.write(json.dumps(data))
    os.system('node JsonToJs udc_mid4.json udc_mid4.js')

剩下的流程比较清晰,但还是需手动清理一些代码。最终生成 finall_udc.js

# -*- coding: utf-8 -*-

import re
import subprocess

import requests
import execjs

node = execjs.get()

sum_comments = 0
restaurant_num = 0

session = requests.session()

headers = {
    'User-Agent': 'yuanrenxue.project'
}


def get_m():
    res = session.get('https://match.yuanrenxue.com/match/9', headers=headers)
    try:
        m = re.findall('for\(var\sm=0x1;m<=(\d);m\+\+\)', res.text)[0]
    except IndexError:
        m = re.findall('\(m,(\d)\);m\+\+\)', res.text)[0]
    decrypt_time = re.findall('decrypt,\'(\d{10})', res.text)[0]
    return m, decrypt_time


def get_page_info():
    global sum_comments, restaurant_num
    url = 'https://match.yuanrenxue.com/api/match/9?'
    iter_num, decrypt_time = get_m()
    p = subprocess.Popen(['node', './final_udc.js', iter_num, decrypt_time], stdout=subprocess.PIPE)
    m = p.stdout.read().decode('UTF-8').replace('\n', '')
    cookies = {
        'm': iter_num + str(m) + 'r'
    }
    print(cookies)
    for i in range(1, 6):
        res = session.get(f'{url}page={i}', headers=headers, cookies=cookies).json()
        for val in res['data']:
            sum_comments += val['value']
            restaurant_num += 1


if __name__ == '__main__':
    get_m()
    get_page_info()
    print(sum_comments / restaurant_num)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于您提到的错误TypeError: list indices must be integers or slices, not str,这是因为您在访问列表中的元素时使用了字符串作为索引,而列表的索引必须是整数或切片类型。解决这个错误的方法是使用整数或切片来访问列表中的元素。 关于您提到的猿人js逆向的问,我需要更多的信息才能为您提供具体的答案。对于爬虫编写,您可以使用Python的各种库(如Requests、BeautifulSoup、Scrapy等)来获取网页的内容,并进一步解析和处理。您可以使用这些库发送HTTP请求获取网页内容,然后使用解析库来提取您需要的数据。 爬虫编写的一般步骤如下: 1. 导入所需的库 2. 发送HTTP请求获取网页内容 3. 使用解析库解析网页内容 4. 提取所需的数据 5. 进行数据的进一步处理和存储 您可以根据具体的需求和网站的结构进行相应的编写和调试。如果您需要更具体的帮助,请提供更多的信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Python:TypeError: list indices must be integers or slices, not str报错解决及原理](https://blog.csdn.net/hhd1988/article/details/128031602)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Python BeautifulSoup [解决方法] TypeError: list indices must be integers or slices, not str](https://download.csdn.net/download/weixin_38590567/14871394)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值