feat: 增加多版本控制、增加其它瑞数网站适配、动态执行逻辑重构

This commit is contained in:
rnet 2024-03-28 18:46:50 +08:00
parent 9a07c459d8
commit 8771a69836
65 changed files with 868 additions and 1089 deletions

View File

@ -6,17 +6,19 @@
**点赞是我坚持的动力,希望该研究也能给一样好奇瑞数原理的人答疑解惑。**
作者最新开源项目(补环境框架sdenv)推荐:[sdenv](https://github.com/pysunday/sdenv)
## 0. 声明
该项目下代码仅用于个人学习、研究或欣赏。通过使用该仓库相关代码产生的风险与仓库代码作者无关!
该项目的研究网站仅做参考,项目不鼓励直接请求该研究网站,算法逆向研究请直接使用`example`目录下的样例文件,如:`node main.js makecookie -f example/codes/1-\$_ts.json`。
该项目的研究网站仅做参考,项目不鼓励直接请求该研究网站,算法逆向研究请直接使用`example`目录下的样例文件,如:`node main.js makecookie`(默认为最新版本代码)
该瑞数cookie生成过程中的算法逆向仍存在以下问题
该瑞数cookie生成过程中的算法逆向存在以下变量
1. 预先设置好的配置项,参见:[代码中config的值](https://github.com/pysunday/rs-reverse/blob/main/src/handler/Cookie.js#L32);
2. 代码中`getSubThree`方法中的[数字46228](https://github.com/pysunday/rs-reverse/blob/main/src/handler/Cookie.js#L115)为作者代码格式化且代码修改后运行代码计算的值;
3. 代码中`getSubOne`方法中的[`_random(500, 1000)`](https://github.com/pysunday/rs-reverse/blob/main/src/handler/Cookie.js#L89)为作者电脑运行计算的大概值,此值与浏览器运行环境有关(如电脑配置等);
1. 预先设置好的配置项,参见:`代码中config的值`;
2. 代码中的数字`46228`为作者代码格式化且代码修改后计算出来的方法字符串摘要值;
3. 代码中中的`_random(500, 1000)`为作者电脑运行计算的大概值,此值与浏览器运行环境有关(如电脑配置等);
## 1. 博客文章
@ -150,7 +152,49 @@ Examples:
```
## 3. 技术交流
## 3. 其它
### 3.1. 网站兼容与适配
适配文件配置在目录`./src/adapt/`下,已完成兼容配置:
网站 | 名称 | 参数 | makecode | makecookie | 适配版本 | 是否做逆向验证
---- | ---- | ---- | -------- | ---------- | -------- | --------------
商标网 | cnipa | `-u https://wcjs.sbj.cnipa.gov.cn/sgtmi` | 👌 | 👌 | - | Y
瑞数官网 | riversecurity | `-u https://www.riversecurity.com/resources.shtml -a riversecurity` | 👌 | 👌 | 版本1 | N
具体配置说明请看文档:`./src/adapt/README.md`
### 3.2. 静态文本
当使用本地方式生成动态代码或者cookie时需要预先配置静态文本远程方式由于会动态解析因此远程方式不需要配置静态文本配置文件`./src/config/immucfg_v*.json`,里面包含`cp0`、`cp2`、`globalText1`、`globalText2`、`globalText3`等静态文本字段您可以通过远程命令动态生成如通过makecode命令加远程网址`-u https://wcjs.sbj.cnipa.gov.cn/sgtmi`,执行后生成文件`./output/makecode_input_immucfg.json`即为静态文本配置文件。
### 3.3. 可变配置项
配置文件地址:`./src/config/index.js`,在网站版本更新后需要修改该文件下配置文件以达到继续适配,配置项说明如下
#### 3.3.1. keynameNum
该配置项用于控制变量名数组生成数量,即`$_ts.cp[1]`的值具体原理请看前面博客文章该值会在每次网站更新后发生变动可以通过查看js文件搜索`\n\n\n\n`,在搜索结果后面不远处就可以找到,如:
1. 代码`_$hn=_$f2(0,806,_$at(_$_q))`中的`806`
![图片1](./static/keynameNum1.png)
2. 代码`_$k$=_$cg(0,829,_$ef(_$_V))`中的`829`
![图片2](./static/keynameNum2.png)
#### 3.3.2. offsetConst
动态代码中生成8位解密用的偏移值数组使用主要是里面的键值是任务数组中的值了由于瑞数的任务树是打包时动态生成且值为任务树中最顶层任务生成不好获取因此写死键值可以在gv.r2mka('0-0').task中找到也可以通过动态代码执行报错获取键值。
#### 3.3.3. codemap
瑞数主体循环方法生成的配置文件,用于动态代码使用。
#### 3.3.3. immucfg
该项为版本固定值,当网站未更新时值是不会变的,当需要配置时可以通过`makecode -u url`方式动态生成,如执行:`node main.js makecode -u https://wcjs.sbj.cnipa.gov.cn/sgtmi`后生成的`output/makecode_input_immucfg.json`文件。
## 4. 技术交流
加作者微信进技术交流群: `howduudu_tech`(备注rs-reverse)

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"nsd":53534,"cd":"qhwqrpAlxpLlDsZmqGqxJGGcqrLDDGQRDqEbDGVFqf93qGqFqrLrDpGDEaaErr7cqrLqDGlRDqEqDPlFrr93qGqFqfLkDpGFqqaBrc3cqq9CcfLkDsZlqGqxlq7cqrLqDGlRDrLoxGVFqOZdqSLqDGlZkqLloAEqDGlZrf93qGqFrrLmDpGFqr9dESLoDsZlDGAWcaAOqGqFrualDpGcqrLcDGWRDqEqDGlZrf93qGqFrrLmDpGzqGabvAlTWAEmWO8wE6YtzRBk0.69CU7OXzHcsSD523g5wVCW_z0ec4dXab75qaAuraAkvcarvY2ZxOMShUxiplreseet39T0JuETSuR1pbW2H2OuwbeNhb2SMdlBMUrXFnfz_DeBtKSnFD5SMURNM2LLEFpV1lwKWmrWTsYpsDeIWmFj8beGsV3biQRzwb2XtCNCZKZBF6w.FcduwbeNhb2SMdlBMUrXFT9BBuNbwCYJQV6_K92C8bNMMdxNJ6x6H6VfNTfzQDy.tD6LMCZNMoxLM4mzwb2XtCNCZKZBF6w.Fm_SEVmLs0zWYtpFV0x7A0eR4b26WVf2IltdiYf.wCzLhdJCMC9XFUmBZ1ezQDy.tD6LMCZNMoxLMZqBEVfqUTxQulY7worJwYUCp9xwRD2wpwafiYy7QbfB7Yf3xnTbwDjnh19vhvJCwBf8UP27QbfB7KTCFKg.FvMSMne.wCzLU.lfs2paVOQ0.TJhAUJLIUULROrLF12zphZyKDz6FCGBZ6RBF1yNQKdShCTaMb7LM8fBMn27QbfBacZfRkxwATU6Vbr9wVywWQ9zsC9nJuSiCPlyUbSnFD5SMURNMPzjwBmBhCz6FCGBZ6RBF1yNQKdSUPZvRvwNsWNmFsrkIVrcuUV_VlmSIbOgAPldKK2SMdlBMUrXFnfz_DeBtKSnFD5SMURNMPzjwBmBUP9GFlroSV2aWometvU0V6mu1CE0MeJVAPQgUDNCZKZBF6w.FcduwbeNhb2SMdlBMUrXFnfz_DeBKcg2FChBV62UUKNAwHxK1OmLJoxLnDTKRcqeUC6LMCZNKYabhHSuFPL7h13B_UmC3meFtD6LMCZNMoxLM4mzwb2XtCNCZKe8t1raUkIaY6QTWvRTiB2sRbwH10rM5sJPxufQFvMSMne.wCzLhdJCMC9XFUmBZ1ezQDy.tD6LMCe3InzjwBmBUGZkcK3_0KE4wvJAH6U7J9NbAoRfit2YpoquICYUN27TsCyEIUI3ikJa1TYLw7LniDxz1sTCnOwjJKzWIOO5Jvme8myCFQeUWK0yMoYhuDersK06YUMCiDrDRvTDi7wNp0JNwcLSNkwGROL0tbvXileP3KfmRwp_J0N0HnLSNkwGROL0tbvXiDeVMTZCVt2tpbJnwcLSNkwGROL0tbvXimJPQDJOQZzFFKwUR1NN4OG_M6ffU9.tMTrjY9ZdKZfsVKaaWs0T.DmVHvxbA6vZ19zXADJCJ_R9JmT7A0G_5upGQK3NJOjN3DqeW12XQtRnRDznU9mPjo94VKGNJOjN3DqeW12XQt3zWsaCRDQ4.PTNwGEorqtzqaE6qfY7w52uisAuWuQSNkASHsleHkiwrslZJbpviy0qWOEuragn.s7aJkV5Jki2qaQSWul0qgCue8AAH8QtTcsfHn03AJjQqSizP93m1Hu6xGFIrqQDvaAor1hqGAGXhvKlO3W7SrN74CQ4X3D2cGgSLV2uBkhHZakAPqQiWt0niO0_HuQ4.AWcJqEJJs1zWOlnWuAuWy0Li6e9FmYvjTRAsPSXwn61K2SuMvWTAWzm86RYs6JR4uRvUDYtWkU01vNsVaQlqya6qaAnraV0vHA0InybRKcS3by6hbR6M.mPwKaXRKYL7KmPQ1y2FUiS3KN.hbAL3HSfhCRSwcfG4vVBRbTjtDkzQnef36WLRdmBhCmzRcfvZvQB3KT9Icdg8C3NRCfahdzB3P29FCQB5CSztKpLQcd4MDTShbrG3Mm9FbWX3ogB5bz7tKN.wcdTQ6WNFvJvhdpGMc2.FK0BeDT2tKzNwnd0QDaNFoALFISShCen3cfN4KR9tKf0FCCSFKxu3nzLFBZBMCN2tC2j51eXws3.FUHZhCgS3nzNQ_gBMvY2tC2L_neXFb3.FKu.hCy7MnzNQ50BMvR.tC2u5DABFbrztDu58nejRKqLMHmfhCNX3Pf7_KVBwU7.wo.5h6J9Q1z0RHqBQ6YBt6pu4PeuwU3.wDI4h6JTwvZLQdJ9h6Y.RcfuZKLBwUmOtoh0R1e0wvZLQIaBQKGXwKYX7UmXQCq.wbM_h6mGQ1zCwd7BQKpat6w77UrfF1y03vXSQop9hvpuRMmawKEXwoTa7UwPwnyuRUbSwCNOhvJzRI7BwCNawKmz_1e6IU3.QoI4h6YCRPznQigBwURTt6x451e0FbpftosnRKV6hvrNwMm0MbAXQDYT7UpuwPydRb_S86JLhveLQhm4M6R_t6SaZ1e4FDg.IPdvFvWN36wBh5TBFvRCtCTudqWkrAR3EDDLqawFxbTEqy2Qxnm0rarQXYS.rAq0JAiIWslmqu3lqja"}
{"nsd":46387,"cd":"qxmErrAltfQctAGsqrQqmalixfWqmaQUrqgwlaqUqfQkkP3sqrQrma3iopQlmaV3cqGlEpWqx1lxlu72EALUrc9mmaWiWaAsqrQ_ma3ixfQlmaV3cq9lopQlJsWmlaqUqfQkkP3UrGguqnGqmaAUrAgbmaEEcGAMlaq7rfQokP3sqrQmmaEixXAqmaqUqAgbma3ETOVrJslcrshhJ1iUx8OYBb605W2StvuyjG5krWe3opZWElR7QTIGYxSoVGWmqGQldfLqDmyyxsDsD6xEA0Y51hTZ39zuWOlnNAr1ADAGHY59r1ZfxngTKFEREsN11VYAnDmW1uJAsbbvqY30IDyP14gUiYf8WP7b6p9nWTfItnMDVom9s6wx3_RdQozLUKz.2Am0wOTuxs_9MOWBxnq.HFxLhnmoM0NEzCE_K2YmFVc0M6rNQsRJRLw0Es28KsQL6pQBWOwIKPOww90aIYJnRgYwsVq6AsJcNGSmQ920pPMmM2Gut1q2tWNLhTGThPVb0aJ8UP9GpmX0ACzh1UGaJj2ShYmr1lmMS9T9QPQgUmdHD1lftsRFKwWUs2x6YuAuuKYhp6pzIvttVkrXMPSXAe0HKmGThPVb0aT8UP9GRO12Q2YNYDmbQ4R7WYQ.sb70uaTipcQgUmdHD1lftsxFKwWUR6JLsYrc2Arc8VmkY6hD3lrTIC2Ppw0HKmGThPVb0ap8UP9G3knRporlY6mnsRTnsKNiw9RX9CNnQPQgUmdHD1lftsmFKwWUMlwrK9T6n9RyhUJ.Y6FxID3uFVSApw0HKmGThPVb0ax8UP9GQmuhKmw6JsxCwQRpVCRvs0zqNTlu3PQgUmdHD1lftsWCKFxEhCTaMb7LNDguhCz6FCOsK6RBF1yNQRJRhCTaMbzR0CguhCz6FCOsK6RBF1yNQRJRhCTaMbzR0CguhCz6FCOsK6RBF1yNQRJRhCTaMbzR0CguhCz6FCOsK6RBF1yNQRJRhCTaMbzR0CguhCz6FCOsK6RBF1yNQRJRhCTaMbzR0CguhCz6FCOsM2GftbJ6MwqMt1lNwvYSbbf8hCz6FCOsK6RBFYZ.UZZRMURNMPzINrQ73vY.tc.Ymne6w6wPKFERMURNMPzjP22BUP2RJnPpADeBtKSnFxWRMURNMPzjP22BUP2RJnPpADeBtKSnFxWRMURNMPzjP22BUP2RJnPpADeBtKSnFxWRMURNMPzjP22BUP2RJnPpADeBtKSnFxWRMURNMPzjP22BUP2RJnPpADeBtKSnFxWRMURNMPzjP22BUP2RJnPpADeBtKSnFxWRMURNMPzjP22BU2fIkAUUYuNHRkN0wFGiwUEa1CpDO2qgJTJmQOKoYmQgUspJFhrWw035WvxJ.Y2CYkAy3DXSkoRVWK76MMpHiDqaQoe5N9wNVYlaMu5Vplz1FVrHFZe9wbG53VpGfUQ_KKeDAK5WDCE0JuN2J70MFUq5sbrv9op21vaC1ohoDCE0JuN2J70MFUq5M2RNNawAJ0So3U1WDCE0JuN2J70MFUq5VbrCbTxuYYSLRYDwDC2aHOzzIN2B12pNVKfAzayMY2YAMOMxkkVnRTVZwxyn8KxW1bSDb0Q6iDETUCj48sN2Wbmu3JmVJkle3kVC0Yeaiop2FU1bQDECIuNsMzmVJkle3kVC0YeaiczOWkMoYulStCf0Hgz58bxAp2JYz229wkyTMO1Awvwsw9SOHRETqaWlWGQmukVUF6mCw6ImrkE6JOq5WZ0JWk9SJOAl5YA0WsTGJAsZrkAnrAGCJWGriulCWulZduE4WkaaWkhoJpiuZ5WYHfaZ1PsvicGMX5acqSVUwJqdMxmkeH0nrdaaqAArqPQOOOE5BxXUo_SnlvmfutP7TZX5BWthgBSgDgg28DUQnGsCrOAnWsVnW7GJqaE0qG0TnqAuiOV_WO6oJAWkrAEorHgmqaEnqdqufp2P3b3XRbbJDKxaFcybQN3R3KxXhbY2PS2fMvVXRKCpDKqBRbJ2txSDQcebQUlLvmNXhCRnwnPMYoQB3Ky.txzF3cefMUWLbTNG8n2vICosVDS6tKp.RwJsMCqNRDfj0TJ7wn29FDjhDKpvRnyGMR9RRo9NRKe.0TTBQn2jw6ssUUwGtKz9FeJQMKLNFC2P0TSzQc2.wDBsU6qBMCJTtxYmRceBQbxO0TeaMD7XMKKxYceBMDq.Fxr1hCy7RPzNOalBMvYOtCvhYceXwsl.F3e1hCyXwczN9mlBMbN0tCbKKceXwUE.F3SQhCyTRCqL9mwNhCNfInPAVbABFby2txrRRPejwblLO0aBQ6Sft618pPeu3bZ.wEe3h6JTQ1z0O0lBQCm9t61HAU7BwKSGtEeQ3ceTMbgLO0Rvh6p.31PiAU7BwCW.wNERQKxLhvYNPYQBQKr2t6FFpPeSQKA.wNyoh6rjhvpb9S2aRU0Xwoi8DUr03ny0QNGRQoNChvJ2Op263vZXQCCRDUwj3CA.QxroQKR.wPzaf0lBw6m9t6tWV1eTwvl.QLSch6YeRPzu9mJ2h6xz3KhJDUpXQnyaFRgRwDxuhvr0Or243KGXI611DUzBwPydFESJh6zCMPzZ929B812gMvssYoJLtUx.M3SrhCNT3aQldumQxTNaracGlK9nrAR3ExGlqawFx2fPduA0qaQ6JAs5rqWcJqEorHZTqaWm"}

File diff suppressed because one or more lines are too long

3
example/codes/readme.md Normal file
View File

@ -0,0 +1,3 @@
样例1: 2024-03-20之前版本
样例2: 2024-03-20版本

57
main.js
View File

@ -5,16 +5,14 @@ require('module-alias')(path.dirname(paths.package));
const yargs = require('yargs');
const fs = require('fs');
const makeCode = require('@src/makeCode');
const makeCodeHigh = require('@src/makeCodeHigh');
const makeCookie = require('@src/makeCookie');
const utils = require('@utils/');
const { logger, isValidUrl } = utils;
const { logger, getCode } = utils;
const pkg = require(paths.package);
const request = require('request-promise');
const cheerio = require('cheerio');
const log4js = require('log4js');
const urlresolve = require('url').resolve;
const adapt = require('@src/adapt');
const _get = require('lodash/get');
const gv = require('@src/handler/globalVarible');
function debugLog(level) {
if (level) {
@ -29,32 +27,16 @@ function debugLog(level) {
logger.trace('paths:\n', JSON.stringify(paths, null, 2));
}
const getCode = async (url) => {
if (!isValidUrl(url)) throw new Error('输入链接不正确');
const res = await request(url)
const $ = cheerio.load(res);
const scripts = [...$('script[r=m]')]
const tsscript = scripts.map(ele => $(ele).text()).filter(text => text.includes('$_ts.nsd') && text.includes('$_ts.cd'));
if (!tsscript.length) throw new Error('链接返回结果未找到cd或nsd');
const $_ts = Function('window', tsscript[0] + 'return $_ts')({});
$_ts.metaContent = _get($('meta[r=m]'), '0.attribs.content');
const checkSrc = (src) => src?.split('.').pop() === 'js' ? src : undefined;
const remotes = scripts.map(it => checkSrc(it.attribs.src)).filter(Boolean);
if (!remotes.length) throw new Error('未找到js外链无法提取配置文本请检查!');
for(let src of remotes) {
const jscode = await request(urlresolve(url, src));
if (jscode.includes('r2mKa')) return { $_ts, jscode, html: res };
}
throw new Error('js外链中没有瑞数的代码文件');
}
const commandBuilder = {
f: {
alias: 'file',
describe: '含有nsd, cd值的json文件',
type: 'string',
coerce: (input) => {
if (['1', '2'].includes(input)) input = paths.exampleResolve('codes', `${input}-\$_ts.json`);
if (['1', '2'].includes(input)) {
gv._setAttr('version', Number(input));
input = paths.exampleResolve('codes', `${input}-\$_ts.json`);
}
if (!fs.existsSync(input)) throw new Error(`输入文件不存在: ${input}`);
return JSON.parse(fs.readFileSync(paths.resolve(input), 'utf8'));
}
@ -79,13 +61,17 @@ const commandBuilder = {
const commandHandler = (command, argv) => {
debugLog(argv.level);
const ts = argv.url?.$_ts || argv.file || require(paths.exampleResolve('codes', '1-\$_ts.json'));
const ts = argv.url?.$_ts || argv.file || require(paths.exampleResolve('codes', `${gv.version}-\$_ts.json`));
logger.trace(`传入的$_ts.nsd: ${ts.nsd}`);
logger.trace(`传入的$_ts.cd: ${ts.cd}`);
if (argv.url) {
command(ts, adapt(argv.url.jscode, argv.adapt), argv.url);
} else {
command(ts);
try {
if (argv.url) {
command(ts, adapt(argv.url, argv.adapt), argv.url);
} else {
command(ts);
}
} catch (err) {
logger.error(err.stack);
}
}
@ -100,6 +86,12 @@ module.exports = yargs
builder: commandBuilder,
handler: commandHandler.bind(null, makeCode),
})
.command({
command: 'makecode-high',
describe: '生成动态代码-高级',
builder: commandBuilder,
handler: commandHandler.bind(null, makeCodeHigh),
})
.command({
command: 'makecookie',
describe: '生成动态cookie',
@ -126,7 +118,10 @@ module.exports = yargs
describe: '拥有完整$_ts的json文件',
type: 'string',
coerce: (input) => {
if (['1', '2'].includes(input)) return paths.exampleResolve('codes', `${input}-\$_ts-full.json`);
if (['1', '2'].includes(input)) {
gv._setAttr('version', Number(input));
return paths.exampleResolve('codes', `${input}-\$_ts-full.json`);
}
return input;
}
},

View File

@ -1,6 +1,6 @@
{
"name": "rs-reverse",
"version": "1.5.1",
"version": "1.5.2",
"description": "瑞数算法逆向,website reverse engineering",
"main": "main.js",
"directories": {

43
script/replace_gv_cp2.js Normal file
View File

@ -0,0 +1,43 @@
const paths = require('../utils/paths');
const fs = require('fs');
const path = require('path');
const gvcp2 = [10,31,16,47,24,36,9,240,268435456,18,86,90,134217727,63,12,19,4294967296,4294967295,8192,4,58,1000,200,7,17,65535,65536,42,100,5,256,15,64,40,255,33,224,128,48,13,131072,-1,44,37,52,43,192,604800,32,45,46,92,8,20,51,6,2,11,3,27,134217728,127,57,1024,16843008,8200,2654435769,67108864,28,79,30,8202,4194304,14,65,39,60,123,100000,55,97,34,512,1048576,180,0.01,-100,-0.01,203,8194,4096,126,201,283,56,93,122,120,32768,248,26,21,300,35,86400000,2097151,170,80,98,96,5000,257,102,59,0.5,268435455,23,2000,82,2048,40960,16383,89,0,8203,68,33554432,262144,50000,69,2047,8239,3337565984,164,81,2531011,0.26,1800,8196,0.35,83,8287,110,99,1732584193,72,29,360,252,12288,271733878,101,2097152,-0.26,16777215,2400959708,84,0.9,16843009,6158,56320,75,0.4,0.813264543,30000,111,112,3988292384,8193,7560,8201,254,88,20000,15679,1518500249,0.1,65537,91,165,4023233417,0.6,54,8197,0.8,8195,160,55296,643615,-180,-0.2,-0.9,8199,1001,2562383102,-4,-90,-7,8198,-2,3000,1500,1859775393,3395469782,5089,3285377520,0.2,1048575,133,173,137,153,130,197,199,162,163,191,207,146,154,145,152,190]
function traverseFolder(folderPath) {
fs.readdirSync(folderPath).forEach(file => {
const filePath = path.join(folderPath, file);
if (fs.statSync(filePath).isDirectory()) {
traverseFolder(filePath); // 如果是文件夹,则递归
} else if (file.endsWith('.js')) {
replaceTextInFile(filePath); // 如果是.js文件则替换文本
}
});
}
function replaceTextInFile(filePath) {
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
console.error(`读取文件失败: ${filePath}`);
return;
}
if (!data.includes('gv.cp2')) return;
debugger;
let replacedData = data;
gvcp2.forEach((val, idx) => {
replacedData = replacedData.replace(new RegExp(`gv\\.cp2\\[${idx}\\]`, 'g'), val);
})
fs.writeFile(filePath, replacedData, 'utf8', err => {
if (err) {
console.error(`写入文件失败: ${filePath}`);
return;
}
console.log(`文件更新成功: ${filePath}`);
});
});
}
traverseFolder(paths.srcPath);

View File

@ -1,6 +0,0 @@
module.exports = {
cp0: 'qk`z}qodw}|`c~zw',
cp2: 'wPPR`QO`OQONUP',
globalText1: "'r2mKa'.length",
globalText2: '&Ţfunction',
}

View File

@ -1,6 +1,7 @@
const fs = require('fs');
const logger = require('@utils/logger');
const unescape = require('@utils/unescape');
const findFullString = require('@utils/findFullString');
const gv = require('@src/handler/globalVarible');
const adapts = fs.readdirSync(__dirname, { withFileTypes: true })
.filter(file => file.isDirectory())
@ -10,29 +11,20 @@ const adapts = fs.readdirSync(__dirname, { withFileTypes: true })
return ans;
}, {});
function findFullString(text, start, end) {
let startIdx, endIdx;
do {
if (startIdx <= 0 || endIdx >= text.length - 1) return;
startIdx === undefined && start--;
endIdx === undefined && end++;
if (startIdx === undefined && text[start] === '"' && text[start - 1] !== '\\') {
startIdx = start;
}
if (endIdx === undefined && text[end] === '"' && text[end - 1] !== '\\') {
endIdx = end;
}
} while (startIdx === undefined || endIdx === undefined);
return unescape(text.slice(startIdx + 1, endIdx));
}
module.exports = function(code, name) {
const config = adapts[name] ? adapts[name] : adapts.common;
module.exports = function({ jscode, url }, name) {
if (!name && !url.includes('cnipa')) throw new Error(`请确保url与适配器匹配, 当前已适配:${Object.keys(adapts).join('、')}`);
if (name && !adapts[name]) throw new Error(`传入的适配器名称不存在, 当前已适配:${Object.keys(adapts).join('、')}`);
const config = adapts[name || 'cnipa'];
return Object.entries(config).reduce((ans, [key, val]) => {
const idx = code.indexOf(val);
if (key === 'version') {
if (typeof val !== 'number') throw new Error(`${name}适配配置错误version必须为数字`);
gv._setAttr('version', val);
return ans;
}
const idx = jscode.indexOf(val);
if (idx === -1) throw new Error(`${key}值数据未找到请查看文档src/adapt/readme.md`);
if (code.indexOf(val, idx + val.length) > -1) throw new Error(`${key}对应的值${val}在代码中非唯一,请检查!`);
const fullString = findFullString(code, idx, idx + val.length);
if (jscode.indexOf(val, idx + val.length) > -1) throw new Error(`${key}对应的值${val}在代码中非唯一,请检查!`);
const fullString = findFullString(jscode, val);
return { ...ans, [key]: fullString };
}, {});
}

View File

@ -3,4 +3,5 @@ module.exports = {
cp2: 'g+*`-+`+0`.1`',
globalText1: "'r2mKa'.length",
globalText2: 'function ā(ā){',
version: 1,
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

45
src/config/index.js Normal file
View File

@ -0,0 +1,45 @@
const logger = require('@utils/logger');
const current_version = 2;
/*
keynameNum: 由瑞数动态打包时生成的固定值控制变量名的生成数量
offsetConst(错误的话会导致解析r2mka值解析出错): 动态代码中生成8位解密用的偏移值数组使用主要是里面的键值是任务数组中的值了由于瑞数的任务树是打包时动态生成且值为任务树中最顶层任务生成不好获取因此写死键值可以在gv.r2mka('0-0').task中找到
codemap(工具动态生成): 瑞数主体循环方法生成的配置文件用于动态代码使用
immucfg(-u命令动态生成): 版本固定值
*/
module.exports = (version = current_version) => {
logger.trace(`当前配置版本: ${version}`);
const config = {};
switch (version) {
case 1:
Object.assign(config, {
keynameNum: 806,
offsetConst: {
81: 3,
82: 51,
83: 153,
},
});
break;
case 2:
Object.assign(config, {
keynameNum: 829,
offsetConst: {
91: 3,
92: 51,
93: 153,
},
});
break;
default:
throw new Error(`当前配置版本不存在, 版本编号:${version}`);
}
return {
...config,
codemap: require(`./codemap_v${version}.json`),
immucfg: require(`./immucfg_v${version}.json`),
version: current_version,
};
}

View File

@ -2,13 +2,14 @@ const getScd = require('./getScd');
const globaltext = require('./globaltext');
const dataOper = require('./dataOper');
const arraySwap = require('./arraySwap');
const immutext = require('@src/immutext/');
const initTs = require('./initTs');
const findFullString = require('@/utils/findFullString');
const gv = require('@src/handler/globalVarible');
module.exports = class {
constructor(ts, immucfg) {
this.startTime = new Date().getTime();
this.$_ts = initTs(ts, immucfg);
this.$_ts = initTs(ts, immucfg || gv.config.immucfg);
this.scd = getScd(this.$_ts.nsd);
this.keynames = this.$_ts.cp[1];
this.keycodes = []
@ -16,14 +17,19 @@ module.exports = class {
this.opmate = this.mateOper();
this.opdata = dataOper();
this.r2mkaText = null;
this.immucfg = immucfg || immutext;
this.immucfg = immucfg || gv.config.immucfg;
}
run() {
const codeArr = this.parseGlobalText1();
codeArr.push(this.parseGlobalText2());
codeArr.push("})(", '$_ts', ".scj,", '$_ts', ".aebi);");
const codeStr = codeArr.join('')
const codeStr = codeArr.join('');
if (!this.immucfg.globalText3) {
const subStr = `r2mKa${codeStr.includes('r2mKa0') ? '0' : '1'}`;
this.immucfg.globalText3 = findFullString(codeStr, subStr);
gv._setAttr('config.immucfg', this.immucfg);
}
this.parseTs(codeStr);
this.endTime = new Date().getTime();
return {

1
src/handler/CoderHigh.js Normal file
View File

@ -0,0 +1 @@
// 整站代码还原

View File

@ -25,6 +25,7 @@ const {
numarr2string,
numarrEncrypt,
xor,
runTask,
} = parser;
module.exports = class {
@ -48,6 +49,10 @@ module.exports = class {
rtt: 0, // 往返延时
saveData: false, // 节流模式
},
'window.innerHeight': 938,
'window.innerWidth': 1680,
'window.outerHeight': 1025,
'window.outerWidth': 1680,
}
this.runTime = Math.floor(new Date().getTime() / 1000); // 运行时间
this.startTime = this.runTime - 1; // 模拟浏览器启动时间
@ -55,25 +60,6 @@ module.exports = class {
}
run() {
const { getTaskNumber: gtn } = this;
const cookieBaseArr = numarrJoin(
gv.cp2[58], // 3
this.getSubOne(),
gv.cp2[0], // 10
this.getSubTwo(),
gv.cp2[23], // 7
this.getSubThree(),
gtn('0>one>63-287', 4), // 0
[gtn('0>one>63>one>4-290', 1)], // 0
gv.cp2[55], // 6
this.getSubFour(),
gv.cp2[56], // 2
this.getSubFive(),
gv.cp2[6], // 9
this.getSubSix(),
gv.cp2[39], // 13
[gtn('0>one>55>one>3-189', 6)],
)
return '0' + numarr2string(
encryptMode1([
...numToNumarr4(this.r2mkaTime),
@ -84,102 +70,170 @@ module.exports = class {
numToNumarr4([this.r2mkaTime, this.startTime]),
string2ascii(gv.cp0[399])
),
gv.keys[gv.cp2[56]]
gv.keys[2]
),
encryptMode1(
xor(
numarrEncrypt(cookieBaseArr),
gv.keys[gv.cp2[56]],
gv.cp2[2]
numarrEncrypt(this[`getBasearr_v${gv.version}`]()),
gv.keys[2],
16
),
numarrAddTime(gv.keys[gv.cp2[24]], this.runTime)[0],
numarrAddTime(gv.keys[17], this.runTime)[0],
0
)
)],
numarrAddTime(gv.keys[gv.cp2[2]], this.runTime)[0]
numarrAddTime(gv.keys[16], this.runTime)[0]
)
);
}
getSubOne() {
const { getTaskNumber: gtn } = this;
const pfarr = string2ascii(this.config['window.navigator.platform']);
return [
gtn('0>one>62>one>30-272', 550),
this.config['window.navigator.maxTouchPoints'],
this.config['window.eval.toString().length'],
gtn('0>one>62>one>28-270', 1) | (gtn('0>one>62>one>28-270', 92) << gv.cp2[23]),
...numToNumarr4(uuid(this.config['window.navigator.userAgent'])),
pfarr.length,
...pfarr,
...numToNumarr4(_random(500, 1000)),
...execRandomByNumber(),
gtn('0>one>62>one>12-246', 28),
gtn('0>one>62-235', 36),
...numToNumarr4(Number(hexnum(gv.cp0_96(6, 76))))
]
}
getSubTwo() {
const flag = +ascii2string(gv.keys[24]);
return [
flag > 0 && flag < gv.cp2[52] ? 1 : 0,
gv.cp2[39],
...numToNumarr4(this.r2mkaTime + this.runTime - this.startTime), // ramka串返回的时间 + 当前时间 - 启动时间
...numToNumarr4(+ascii2string(gv.keys[gv.cp2[15]])),
...numToNumarr8(Math.floor(Math.random() * gv.cp2[207]) * gv.cp2[16] + (((this.runTime * 1000) & gv.cp2[17]) >>> 0)),
flag,
]
}
getSubThree() {
const { getTaskNumber: gtn } = this;
return [
...numToNumarr4(Number(hexnum(gv.cp0_96(6, 76)))),
...numToNumarr4(gtn('0-0', 92)),
...numToNumarr2(getFixedNumber()),
...numToNumarr2(46228), // 根据方法的toString()计算
];
}
getSubFour() {
const keyarr = numarrAddTime(gv.keys[gv.cp2[2]])[0];
getBasearr_v2() {
// 第2版计算cookie方法
const name = this.config['window.name'].split('&').reduce((ans, it) => {
const [key, val] = it.split('=');
return { ...ans, [key]: val };
}, {});
return [
1, 0, 0, 0, 0, 0,
...encryptMode2(decrypt(name.$_YWTU || ''), keyarr),
...numToNumarr2(+decode(decrypt(name.$_YVTX || ''))),
];
return numarrJoin(
3,
numarrJoin(
1,
this.config['window.navigator.maxTouchPoints'],
this.config['window.eval.toString().length'],
128,
...numToNumarr4(uuid(this.config['window.navigator.userAgent'])),
string2ascii(this.config['window.navigator.platform']),
...numToNumarr4(_random(500, 1000)),
...execRandomByNumber(),
0,
0,
...numToNumarr4(Number(hexnum('3136373737323136'))),
...numToNumarr4(0),
...numToNumarr2(this.config['window.innerHeight']),
...numToNumarr2(this.config['window.innerWidth']),
...numToNumarr2(this.config['window.outerHeight']),
...numToNumarr2(this.config['window.outerWidth']),
),
10, // 下标43
[
0, // 运行时代码中传入的初始数组长度由于传入的是空数组因此为0
1, // 任务编号0>one>36>one>2-131的任务列表取得
...numToNumarr4(this.r2mkaTime + this.runTime - this.startTime), // ramka串返回的时间 + 当前时间 - 启动时间
...numToNumarr4(+ascii2string(gv.keys[19])),
...numToNumarr8(Math.floor(Math.random() * 1048575) * 4294967296 + (((this.runTime * 1000) & 4294967295) >>> 0)),
],
7, // 下标63
[
...numToNumarr4(16777216), // gv.cp2取得
...numToNumarr4(0), // 任务编号0-0的任务列表取得
...numToNumarr2(getFixedNumber()), // 固定值5900
...numToNumarr2(46228), // 根据方法的toString()计算
],
0, // 任务编号0>one>63-287的任务列表取得
[0], // 任务编号0>one>63>one>4-290的任务列表取得
6, // 下标80
[ // 编号510方法执行返回
1,
...numToNumarr2(0),
...numToNumarr2(0),
0,
...encryptMode2(decrypt(name.$_YWTU || ''), numarrAddTime(gv.keys[16])[0]),
...numToNumarr2(+decode(decrypt(name.$_YVTX || ''))),
],
2, // 下标98
[
factorial(5) - factorial(3) * 2 + 100, // 100是cp2里取出来的可能随版本变动
203, // cp2[76]检测window.HTMLFormElement是否存在
102, // cp2[120]检测document.createElement('from')
103, // 检测window.top值是否为null
],
9, // 下标104
[
0 | 8, // 8为cp2中的值
['bluetooth', 'cellular', 'ethernet', 'wifi', 'wimax'].indexOf(this.config['window.navigator.connection'].type) + 1,
],
13,
[0],
)
}
getSubFive() {
return [
factorial(gv.cp2[29]) - factorial(gv.cp2[58]) * gv.cp2[56],
fibonacci(gv.cp2[57]) + gv.cp2[43],
factorial(gv.cp2[55]) / gv.cp2[19],
gv.cp2[57],
]
}
getSubSix() {
// 网络与电量信息
const { connType } = this.config['window.navigator.connection'];
const { charging, chargingTime, level } = this.config['window.navigator.battery']
const connTypeIdx = ['bluetooth', 'cellular', 'ethernet', 'wifi', 'wimax'].indexOf(connType) + 1;
let oper = 0;
if (level) oper |= gv.cp2[56];
if (charging) oper |= 1;
if (connTypeIdx !== undefined) oper |= gv.cp2[52]
return [
oper,
level * 100,
chargingTime >> gv.cp2[52],
chargingTime & gv.cp2[34],
connTypeIdx,
]
getBasearr_v1() {
// 第1版计算cookie方法
const { getTaskNumber: gtn } = this;
return numarrJoin(
3,
numarrJoin(
gtn('0>one>62>one>30-272', 550),
this.config['window.navigator.maxTouchPoints'],
this.config['window.eval.toString().length'],
gtn('0>one>62>one>28-270', 1) | (gtn('0>one>62>one>28-270', 92) << 7),
...numToNumarr4(uuid(this.config['window.navigator.userAgent'])),
string2ascii(this.config['window.navigator.platform']),
...numToNumarr4(_random(500, 1000)),
...execRandomByNumber(),
gtn('0>one>62>one>12-246', 28),
gtn('0>one>62-235', 36),
...numToNumarr4(Number(hexnum(gv.cp0_96(6, 76))))
),
10,
(() => {
const flag = +ascii2string(gv.keys[24]);
return [
flag > 0 && flag < 8 ? 1 : 0,
13,
...numToNumarr4(this.r2mkaTime + this.runTime - this.startTime), // ramka串返回的时间 + 当前时间 - 启动时间
...numToNumarr4(+ascii2string(gv.keys[19])),
...numToNumarr8(Math.floor(Math.random() * 1048575) * 4294967296 + (((this.runTime * 1000) & 4294967295) >>> 0)),
flag,
];
})(),
7,
[
...numToNumarr4(Number(hexnum(gv.cp0_96(6, 76)))),
...numToNumarr4(gtn('0-0', 92)),
...numToNumarr2(getFixedNumber()),
...numToNumarr2(46228), // 根据方法的toString()计算
],
0,
[0],
6,
(() => {
const name = this.config['window.name'].split('&').reduce((ans, it) => {
const [key, val] = it.split('=');
return { ...ans, [key]: val };
}, {});
return [
1, 0, 0, 0, 0, 0,
...encryptMode2(decrypt(name.$_YWTU || ''), numarrAddTime(gv.keys[16])[0]),
...numToNumarr2(+decode(decrypt(name.$_YVTX || ''))),
];
})(),
2,
[
factorial(5) - factorial(3) * 2,
fibonacci(11) + 37,
factorial(6) / 4,
11,
],
9,
(() => {
const { connType } = this.config['window.navigator.connection'];
const { charging, chargingTime, level } = this.config['window.navigator.battery']
const connTypeIdx = ['bluetooth', 'cellular', 'ethernet', 'wifi', 'wimax'].indexOf(connType) + 1;
let oper = 0;
if (level) oper |= 2;
if (charging) oper |= 1;
if (connTypeIdx !== undefined) oper |= 8
return [
oper,
level * 100,
chargingTime >> 8,
chargingTime & 255,
connTypeIdx,
]
})(),
13,
[0],
);
}
getTaskNumber(name, idx) {

View File

@ -1,10 +1,23 @@
const _merge = require('lodash/merge');
const _chunk = require('lodash/chunk');
const _get = require('lodash/get');
const _set = require('lodash/set');
const config = require('@src/config/');
const cache = {};
class GlobalVarible {
get config() {
// 不同版本的可变配置
if (!cache.config) {
cache.config = config(cache.version);
}
return cache.config
}
get version() {
// 代码版本
return cache.version || this.config.version;
}
get metaContent() {
return cache.metaContent;
}
@ -14,6 +27,12 @@ class GlobalVarible {
get cfgnum() {
return cache.cfgnum;
}
get decryptKeys() {
return cache.decryptKeys;
}
get basestr() {
return 'qrcklmDoExthWJiHAp1sVYKU3RFMQw8IGfPO92bvLNj.7zXBaSnu0TC6gy_4Ze5d{}|~ !#$%()*+,-;=?@[]^';
}
get utils() {
return cache.utils;
}
@ -51,7 +70,7 @@ class GlobalVarible {
return cache[attr];
}
_setAttr(attr, value) {
cache[attr] = value;
_set(cache, attr, value);
if (attr === 'cp0') {
cache.cp0_96 = _chunk(value, 96);
}

View File

@ -1,5 +1,5 @@
const immutext = require('@src/immutext/');
const grenKeys = require('./grenKeys');
const gv = require('@src/handler/globalVarible');
function grenJf () {
const flags = [1, 0, 0];
@ -9,10 +9,10 @@ function grenJf () {
return !flag;
}
module.exports = function(defdata, immucfg = immutext.$_ts) {
module.exports = function(defdata, immucfg) {
const cp = [];
cp[0] = immucfg.cp0;
cp[1] = grenKeys(806, defdata.nsd);
cp[1] = grenKeys(gv.config.keynameNum, defdata.nsd);
cp[2] = immucfg.cp2;
cp[6] = '';
return {

View File

@ -1,53 +0,0 @@
const gv = require('@src/handler/globalVarible');
function makeCfgnum() {
const arr1 = [[], [], [], [], []];
const arr2 = [[], [], [], [], []];
const arr1_4 = arr1[4];
const arr2_4 = arr2[4];
const one = [];
const two = [];
let i, j, temp;
for (i = 0; i < gv.cp2[30]; i++) {
two[(one[i] = i << 1 ^ (i >> gv.cp2[23]) * gv.cp2[93]) ^ i] = i;
}
for (i = j = 0; !arr1_4[i]; i ^= one[i] || 1, j = two[j] || 1) {
temp = j ^ j << 1 ^ j << gv.cp2[56] ^ j << gv.cp2[58] ^ j << gv.cp2[19];
temp = temp >> gv.cp2[52] ^ temp & gv.cp2[34] ^ gv.cp2[143];
arr1_4[i] = temp;
arr2_4[temp] = i;
}
for (i = 0; i < gv.cp2[30]; i++) {
arr2_4[arr1_4[i]] = i;
}
for (i = 0; i < gv.cp2[30]; i++) {
let ele1 = one[one[one[i]]] * gv.cp2[158] ^ one[one[i]] * gv.cp2[177] ^ one[i] * gv.cp2[111] ^ i * gv.cp2[64];
let ele2 = one[arr1_4[i]] * gv.cp2[111] ^ arr1_4[i] * gv.cp2[64];
for (j = 0; j < gv.cp2[19]; j++) {
arr1[j][i] = ele2 = ele2 << gv.cp2[4] ^ ele2 >>> gv.cp2[52];
arr2[j][arr1_4[i]] = ele1 = ele1 << gv.cp2[4] ^ ele1 >>> gv.cp2[52];
}
}
for (i = 0; i < gv.cp2[29]; i++) {
arr1[i] = arr1[i].slice(0);
arr2[i] = arr2[i].slice(0);
}
return [arr1, arr2]
}
function makeBignum() {
const arr = [];
for (let i = 0; i < gv.cp2[30]; i++) {
let item = i;
for (_$iv = 0; _$iv < gv.cp2[52]; _$iv++) {
item = item & 1 ? gv.cp2[167] ^ item >>> 1 : item >>> 1;
}
arr[i] = item;
}
return arr;
}
exports.init = function() {
gv._setAttr('bignum', makeBignum());
gv._setAttr('cfgnum', makeCfgnum());
}

View File

@ -2,10 +2,10 @@
const gv = require('@src/handler/globalVarible');
module.exports = function (numarr, start = 0, end = numarr.length) {
const arr = new Array(Math.ceil(numarr.length / gv.cp2[120]));
const arr = new Array(Math.ceil(numarr.length / 40960));
let idx = 0;
while (start < end - gv.cp2[120]) {
arr[idx++] = String.fromCharCode(...numarr.slice(start, start += gv.cp2[120]));
while (start < end - 40960) {
arr[idx++] = String.fromCharCode(...numarr.slice(start, start += 40960));
}
if (start < end) {
arr[idx++] = String.fromCharCode(...numarr.slice(start, end));

View File

@ -3,32 +3,32 @@ const combine4 = require('./combine4');
const gv = require('@src/handler/globalVarible');
module.exports = function (numarr1, numarr2) {
const arr = new Array(numarr1.length - gv.cp2[52]);
const arr = new Array(numarr1.length - 8);
const comb1 = combine4(numarr1);
const comb2 = combine4(numarr2);
let first = comb1[0];
let second = comb1[1];
let current, next, temp;
let cursor = 0;
for (let idx = gv.cp2[56]; idx < comb1.length - 1; cursor += 8, idx += 2) {
for (let idx = 2; idx < comb1.length - 1; cursor += 8, idx += 2) {
current = comb1[idx];
next = comb1[idx + 1];
temp = gv.cp2[132];
for (let i = 0; i < gv.cp2[48]; ++i) {
next = next - ((current << gv.cp2[19] ^ current >> gv.cp2[29] & gv.cp2[12]) + current ^ temp + comb2[temp >> gv.cp2[57] & gv.cp2[105] & gv.cp2[58]]) & gv.cp2[17];
temp = temp - gv.cp2[66] & gv.cp2[17];
current = current - ((next << gv.cp2[19] ^ next >> gv.cp2[29] & gv.cp2[12]) + next ^ temp + comb2[temp & gv.cp2[58]]) & gv.cp2[17];
temp = 3337565984;
for (let i = 0; i < 32; ++i) {
next = next - ((current << 4 ^ current >> 5 & 134217727) + current ^ temp + comb2[temp >> 11 & 2097151 & 3]) & 4294967295;
temp = temp - 2654435769 & 4294967295;
current = current - ((next << 4 ^ next >> 5 & 134217727) + next ^ temp + comb2[temp & 3]) & 4294967295;
}
first = current ^ first;
second = next ^ second;
arr[cursor] = first >> gv.cp2[4] & gv.cp2[34];
arr[cursor + 1] = first >> gv.cp2[2] & gv.cp2[34];
arr[cursor + 2] = first >> gv.cp2[52] & gv.cp2[34];
arr[cursor + 3] = first & gv.cp2[34];
arr[cursor + 4] = second >> gv.cp2[4] & gv.cp2[34];
arr[cursor + 5] = second >> gv.cp2[2] & gv.cp2[34];
arr[cursor + 6] = second >> gv.cp2[52] & gv.cp2[34];
arr[cursor + 7] = second & gv.cp2[34];
arr[cursor] = first >> 24 & 255;
arr[cursor + 1] = first >> 16 & 255;
arr[cursor + 2] = first >> 8 & 255;
arr[cursor + 3] = first & 255;
arr[cursor + 4] = second >> 24 & 255;
arr[cursor + 5] = second >> 16 & 255;
arr[cursor + 6] = second >> 8 & 255;
arr[cursor + 7] = second & 255;
first = comb1[idx];
second = comb1[idx + 1];
}

View File

@ -3,9 +3,9 @@
const gv = require('@src/handler/globalVarible');
module.exports = function(numarr) {
const arr = new Array(numarr.length / gv.cp2[19]);
const arr = new Array(numarr.length / 4);
for (let cursor = 0, idx = 0; cursor < numarr.length; cursor += 4, idx++) {
arr[idx] = numarr[cursor] << gv.cp2[4] | numarr[cursor + 1] << gv.cp2[2] | numarr[cursor + 2] << gv.cp2[52] | numarr[cursor + 3];
arr[idx] = numarr[cursor] << 24 | numarr[cursor + 1] << 16 | numarr[cursor + 2] << 8 | numarr[cursor + 3];
}
return arr;
}

View File

@ -1,3 +1,4 @@
const ascii2string = require('./ascii2string');
const gv = require('@src/handler/globalVarible');
function trans(numarr) {
@ -6,31 +7,31 @@ function trans(numarr) {
for (var idx = 0; idx < numarr.length; idx++) {
const num = numarr[idx];
let val;
if (num < gv.cp2[37]) {
if (num < 128) {
val = num;
} else if (num < gv.cp2[46]) {
} else if (num < 192) {
val = mark;
} else if (num < gv.cp2[36]) {
val = (num & gv.cp2[13]) << gv.cp2[55] | numarr[idx + 1] & gv.cp2[13];
} else if (num < 224) {
val = (num & 63) << 6 | numarr[idx + 1] & 63;
idx++;
} else if (num < gv.cp2[7]) {
val = (num & gv.cp2[31]) << gv.cp2[14] | (numarr[idx + 1] & gv.cp2[13]) << gv.cp2[55] | numarr[idx + gv.cp2[56]] & gv.cp2[13];
idx += gv.cp2[56];
} else if (num < gv.cp2[99]) {
val = (num & gv.cp2[23]) << gv.cp2[9] | (numarr[idx + 1] & gv.cp2[13]) << gv.cp2[14] | (numarr[idx + gv.cp2[56]] & gv.cp2[13]) << gv.cp2[55] | numarr[idx + gv.cp2[58]] & gv.cp2[13];
idx += gv.cp2[58];
} else if (num < gv.cp2[148]) {
} else if (num < 240) {
val = (num & 15) << 12 | (numarr[idx + 1] & 63) << 6 | numarr[idx + 2] & 63;
idx += 2;
} else if (num < 248) {
val = (num & 7) << 18 | (numarr[idx + 1] & 63) << 12 | (numarr[idx + 2] & 63) << 6 | numarr[idx + 3] & 63;
idx += 3;
} else if (num < 252) {
val = mark;
idx += gv.cp2[19];
} else if (num < gv.cp2[171]) {
idx += 4;
} else if (num < 254) {
val = mark;
idx += gv.cp2[29];
idx += 5;
} else {
val = mark;
}
if (val > gv.cp2[25]) {
val -= gv.cp2[26];
ans.push((val >> gv.cp2[0]) + gv.cp2[187], val % gv.cp2[63] + gv.cp2[160]);
if (val > 65535) {
val -= 65536;
ans.push((val >> 10) + 55296, val % 1024 + 56320);
} else {
ans.push(val);
}
@ -38,18 +39,6 @@ function trans(numarr) {
return ans;
}
function join(numarr, start = 0, end = numarr.length) {
const ans = new Array(Math.ceil(numarr.length / gv.cp2[120]));
let idx = 0;
while (start < end - gv.cp2[120]) {
ans[idx++] = String.fromCharCode(...numarr.slice(start, start += gv.cp2[120]));
}
if (start < end) {
ans[idx++] = String.fromCharCode(...numarr.slice(start, end));
}
return ans.join('');
}
module.exports = function(numarr) {
return join(trans(numarr));
return ascii2string(trans(numarr));
}

View File

@ -1,21 +1,7 @@
const gv = require('@src/handler/globalVarible');
let datas = undefined;
module.exports = function(str) {
if (!datas) {
datas = gv.cp0_96(7, 41).split('').reduce((ans, key, idx) => {
const code = key.charCodeAt()
ans[0][code] = idx << gv.cp2[56];
ans[1][code] = idx >> gv.cp2[19];
ans[2][code] = (idx & gv.cp2[31]) << gv.cp2[19];
ans[3][code] = idx >> gv.cp2[56];
ans[4][code] = (idx & gv.cp2[58]) << gv.cp2[55];
ans[5][code] = idx;
return ans
}, [{}, {}, {}, {}, {}, { ...new Array(255).fill(-1) }])
}
const [data1, data2, data3, data4, data5, data6] = datas;
const [data1, data2, data3, data4, data5, data6] = gv.decryptKeys;
const ans = []
for(let i = 0; i < str.length; i += 4) {
let [one, two, three, four] = [0, 1, 2, 3].map(it => {

View File

@ -8,622 +8,65 @@ module.exports = function(...params) {
return dynamicExec(...params);
} catch (err) {
logger.error(String(err));
process.exit();
throw err;
} finally {
logger.trace('执行结束!');
}
}
function dynamicExec(taskItem, start = 0, args = [], loop_res = {}, global_res = {}) {
const codemap = gv.config.codemap;
const { key, taskarr: task } = taskItem;
args = monitor(args, '${key}_args', { getLog: true, setLog: true });
args = monitor(args, `${key}_args`, { getLog: true, setLog: true });
loop_res = monitor(loop_res, `${key}_loop_res`, { getLog: true, setLog: true });
global_res = monitor(global_res, `${key}_global_res`, { getLog: true, setLog: true });
logger.trace(`动态代码运行,任务列表:${key}, 起点:${start},长度:${task.length}`);
const data = [];
const ret = [];
ret[0] = args;
ret[2] = [
'window、',
args,
];
let target, tarkey, d_cursor = 0, temp1, temp2, temp3, temp4, t_cursor;
let runtimes = 0;
const len = task.length;
const notCheckTask = [11, 15, 27, 32, 48, 51, 59, 84, 104, 109];
for (t_cursor = start; t_cursor < len; t_cursor++) {
logger.trace(`${notCheckTask.includes(task[t_cursor]) ? '[no]' : '[ok]'}${++runtimes}, ${t_cursor}${key} 运行 case${task[t_cursor]}`);
switch (task[t_cursor]) {
case 0:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] * temp1;
data[d_cursor++] = temp1;
break;
case 1:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] & temp1;
data[d_cursor++] = temp1;
break;
case 2:
data[d_cursor++] = ret[0][task[++t_cursor]];
break;
case 3:
data[d_cursor++] = true;
break;
case 4:
tarkey = task[++t_cursor];
temp1 = data[--d_cursor];
!temp1 ? (t_cursor += tarkey, ++d_cursor) : 0;
break;
case 5:
temp1 = data[--d_cursor];
setTarget();
temp1 = target[tarkey] |= temp1;
break;
case 6:
data[d_cursor++] = ret[2][task[++t_cursor]];
break;
case 7:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] !== temp1;
data[d_cursor++] = temp1;
break;
case 8:
d_cursor -= 2;
temp1 = d_cursor;
setTarget();
target = target[tarkey];
data[d_cursor++] = target(data[temp1], data[temp1 + 1]);
break;
case 9:
d_cursor--;
temp1 = d_cursor;
setTarget();
target = target[tarkey];
data[d_cursor++] = target(data[temp1]);
break;
case 10:
temp2 = task[++t_cursor];
t_cursor += temp2;
break;
case 11:
// temp3 = task[++t_cursor];
// data[d_cursor++] = ret[3][temp3][task[++t_cursor]];
break;
case 12:
return data[--d_cursor];
case 13:
d_cursor -= 3;
temp1 = d_cursor;
setTarget();
target = target[tarkey];
temp1 = target(data[temp1], data[temp1 + 1], data[temp1 + 2]);
break;
case 14:
temp2 = task[++t_cursor];
t_cursor -= temp2;
break;
case 15:
// temp3 = task[++t_cursor];
// data[d_cursor++] = ret[1][temp3][task[++t_cursor]];
break;
case 16:
d_cursor--;
temp1 = d_cursor;
setTarget();
temp1 = target[tarkey](data[temp1]);
break;
case 17:
d_cursor--;
temp1 = d_cursor;
setTarget();
data[d_cursor++] = target[tarkey](data[temp1]);
break;
case 18:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] in temp1;
data[d_cursor++] = temp1;
break;
case 19:
temp1 = data[--d_cursor];
target = data[d_cursor - 1];
target[keycodes[task[++t_cursor]]] = temp1;
break;
case 20:
data[d_cursor++] = [];
break;
case 21:
task[t_cursor] = 26;
tarkey = task[++t_cursor];
temp1 = keycodes[tarkey];
task[t_cursor] = temp1;
data[d_cursor++] = temp1;
break;
case 22:
temp1 = data[--d_cursor];
setTarget();
temp1 = target[tarkey] += temp1;
break;
case 23:
data[d_cursor++] = loop_res[task[++t_cursor]];
break;
case 24:
tarkey = data[--d_cursor];
target = data[--d_cursor];
break;
case 25:
temp1 = data[--d_cursor];
setTarget();
target[tarkey] = temp1;
break;
case 26:
data[d_cursor++] = task[++t_cursor];
break;
case 27:
// temp3 = task[++t_cursor];
// tarkey = task[++t_cursor];
// target = ret[3][temp3];
break;
case 28:
setTarget();
data[d_cursor++] = target[tarkey]();
break;
case 29:
d_cursor -= 2;
temp1 = d_cursor;
setTarget();
data[d_cursor++] = target[tarkey](data[temp1], data[temp1 + 1]);
break;
case 30:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] > temp1;
data[d_cursor++] = temp1;
break;
case 31:
setTarget();
target = target[tarkey];
data[d_cursor++] = target();
break;
case 32:
// _$cG(_$$I, task[++t_cursor], task[++t_cursor], temp2 = task[++t_cursor], task[++t_cursor], t_cursor + 1, ret[2], ret);
// ret[4] ? t_cursor = len : t_cursor += temp2;
break;
case 33:
tarkey = task[++t_cursor];
target = ret[0];
break;
case 34:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] != temp1;
data[d_cursor++] = temp1;
break;
case 35:
setTarget();
target = target[tarkey];
temp1 = target();
break;
case 36:
d_cursor--;
temp1 = d_cursor;
setTarget();
target = target[tarkey];
temp1 = target(data[temp1]);
break;
case 37:
task[t_cursor] = 92;
tarkey = keywords[task[++t_cursor]];
task[t_cursor] = tarkey;
target = data[--d_cursor];
break;
case 38:
temp1 = data[--d_cursor];
temp2 = task[++t_cursor];
temp1 ? 0 : t_cursor += temp2;
break;
case 39:
tarkey = task[++t_cursor];
temp1 = data[--d_cursor];
temp1 ? (t_cursor += tarkey, ++d_cursor) : 0;
break;
case 40:
data[d_cursor++] = {};
break;
case 41:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] == temp1;
data[d_cursor++] = temp1;
break;
case 42:
temp1 = data[--d_cursor];
target = data[--d_cursor];
data[d_cursor++] = target[temp1];
break;
case 43:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] < temp1;
data[d_cursor++] = temp1;
break;
case 44:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] === temp1;
data[d_cursor++] = temp1;
break;
case 45:
data[d_cursor++] = global_res[task[++t_cursor]];
break;
case 46:
task[t_cursor] = 87;
tarkey = keywords[task[++t_cursor]];
task[t_cursor] = tarkey;
temp1 = data[--d_cursor];
data[d_cursor++] = temp1[tarkey];
break;
case 47:
d_cursor -= 2;
temp1 = d_cursor;
setTarget();
target = target[tarkey];
temp1 = target(data[temp1], data[temp1 + 1]);
break;
case 48:
// tarkey = task[++t_cursor];
// data[d_cursor++] = _$_w(_$$I._$hW[tarkey], ret);
break;
case 49:
d_cursor -= 2;
temp1 = d_cursor;
setTarget();
temp1 = target[tarkey](data[temp1], data[temp1 + 1]);
break;
case 50:
temp1 = typeof data[--d_cursor];
data[d_cursor++] = temp1;
break;
case 51:
// temp2 = task[++t_cursor];
// temp4 = data.slice(d_cursor - temp2, d_cursor);
// d_cursor -= temp2;
// setTarget();
// data[d_cursor++] = _$fH(target[tarkey], temp4);
break;
case 52:
temp1 = data[--d_cursor];
target = data[d_cursor - 1];
target[keywords[task[++t_cursor]]] = temp1;
break;
case 53:
temp1 = data[--d_cursor];
data[d_cursor++] = !temp1;
break;
case 54:
tarkey = task[++t_cursor];
target = loop_res;
break;
case 55:
temp1 = target[tarkey]++;
break;
case 56:
ret[4] = 2;
t_cursor = len;
break;
case 57:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] - temp1;
data[d_cursor++] = temp1;
break;
case 58:
data[d_cursor++] = false;
break;
case 59:
// task[t_cursor] = 26;
// tarkey = task[++t_cursor];
// temp1 = _$kG[tarkey];
// task[t_cursor] = temp1;
// data[d_cursor++] = temp1;
break;
case 60:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] + temp1;
data[d_cursor++] = temp1;
break;
case 61:
temp1 = data[--d_cursor];
target = data[d_cursor - 1];
target.push(temp1);
break;
case 62:
tarkey = task[++t_cursor];
target = global_res;
break;
case 63:
tarkey = task[++t_cursor];
target = ret[2];
break;
case 64:
break;
case 65:
task[t_cursor] = 87;
tarkey = keycodes[task[++t_cursor]];
task[t_cursor] = tarkey;
temp1 = data[--d_cursor];
data[d_cursor++] = temp1[tarkey];
break;
case 66:
data[d_cursor++] = null;
break;
case 67:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] << temp1;
data[d_cursor++] = temp1;
break;
case 68:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] + temp1;
break;
case 69:
d_cursor -= 5;
temp1 = d_cursor;
setTarget();
data[d_cursor++] = target[tarkey](data[temp1], data[temp1 + 1], data[temp1 + 2], data[temp1 + 3], data[temp1 + 4]);
break;
case 70:
data[d_cursor++] = target[tarkey]++;
break;
case 71:
temp2 = task[++t_cursor];
d_cursor -= temp2;
temp4 = data.slice(d_cursor, d_cursor + temp2);
setTarget();
temp1 = target[tarkey].apply(target, temp4);
break;
case 72:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] % temp1;
data[d_cursor++] = temp1;
break;
case 73:
data[d_cursor++] = ++target[tarkey];
break;
case 74:
d_cursor -= 4;
temp1 = d_cursor;
setTarget();
target = target[tarkey];
temp1 = target(data[temp1], data[temp1 + 1], data[temp1 + 2], data[temp1 + 3]);
break;
case 75:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] >= temp1;
data[d_cursor++] = temp1;
break;
case 76:
temp1 = task[++t_cursor];
break;
case 77:
temp1 = target[tarkey]--;
break;
case 78:
tarkey = task[++t_cursor];
temp1 = temp1[tarkey];
break;
case 79:
d_cursor -= 3;
temp1 = d_cursor;
setTarget();
target = target[tarkey];
data[d_cursor++] = target(data[temp1], data[temp1 + 1], data[temp1 + 2]);
break;
case 80:
tarkey = task[++t_cursor];
data[d_cursor++] = temp1[tarkey];
break;
case 81:
d_cursor -= 4;
temp1 = d_cursor;
setTarget();
data[d_cursor++] = target[tarkey](data[temp1], data[temp1 + 1], data[temp1 + 2], data[temp1 + 3]);
break;
case 82:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] <= temp1;
data[d_cursor++] = temp1;
break;
case 83:
tarkey = task[++t_cursor];
temp1 = data[--d_cursor];
!temp1 ? t_cursor += tarkey : 0;
break;
case 84:
// temp1 = data[--d_cursor];
// tarkey = task[++t_cursor];
// target = _$ke[tarkey];
// temp2 = target[temp1];
// temp2 == _$an ? temp2 = task[++t_cursor] : ++t_cursor;
// t_cursor += temp2;
break;
case 85:
setTarget();
temp1 = target[tarkey]();
break;
case 86:
temp1 = delete target[tarkey];
break;
case 87:
tarkey = task[++t_cursor];
temp1 = data[--d_cursor];
data[d_cursor++] = temp1[tarkey];
break;
case 88:
temp1 = data[--d_cursor];
data[d_cursor++] = ~temp1;
break;
case 89:
temp1 = -data[--d_cursor];
data[d_cursor++] = temp1;
break;
case 90:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] >>> temp1;
data[d_cursor++] = temp1;
break;
case 91:
temp1 = data[--d_cursor];
setTarget();
temp1 = target[tarkey] ^= temp1;
break;
case 92:
tarkey = task[++t_cursor];
target = data[--d_cursor];
break;
case 93:
d_cursor -= 3;
temp1 = d_cursor;
setTarget();
temp1 = target[tarkey](data[temp1], data[temp1 + 1], data[temp1 + 2]);
break;
case 94:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] / temp1;
data[d_cursor++] = temp1;
break;
case 95:
d_cursor -= 3;
temp1 = d_cursor;
setTarget();
data[d_cursor++] = target[tarkey](data[temp1], data[temp1 + 1], data[temp1 + 2]);
break;
case 96:
d_cursor -= 4;
temp1 = d_cursor;
setTarget();
temp1 = target[tarkey](data[temp1], data[temp1 + 1], data[temp1 + 2], data[temp1 + 3]);
break;
case 97:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] instanceof temp1;
data[d_cursor++] = temp1;
break;
case 98:
temp1 = data[--d_cursor];
setTarget();
temp1 = target[tarkey] &= temp1;
break;
case 99:
task[t_cursor] = 92;
tarkey = keycodes[task[++t_cursor]];
task[t_cursor] = tarkey;
target = data[--d_cursor];
break;
case 100:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] | temp1
data[d_cursor++] = temp1;
break;
case 101:
temp2 = task[++t_cursor], temp1 = data[--d_cursor], t_cursor++;
t_cursor += temp2 - 1;
break;
case 102:
temp1 = ++target[tarkey];
break;
case 103:
temp1 = data[--d_cursor];
setTarget();
target[tarkey] = temp1;
data[d_cursor++] = temp1;
break;
case 104:
// temp3 = task[++t_cursor];
// tarkey = task[++t_cursor];
// target = ret[1][temp3];
break;
case 105:
tarkey = task[++t_cursor];
temp1 = data[--d_cursor];
temp1 = temp1[tarkey];
break;
case 106:
d_cursor -= 4;
temp1 = d_cursor;
setTarget();
target = target[tarkey];
data[d_cursor++] = target(data[temp1], data[temp1 + 1], data[temp1 + 2], data[temp1 + 3]);
break;
case 107:
data[d_cursor++] = --target[tarkey];
break;
case 108:
--d_cursor;
target = data;
tarkey = d_cursor;
break;
case 109:
// temp2 = task[++t_cursor];
// temp4 = data.slice(d_cursor - temp2, d_cursor);
// d_cursor -= temp2;
// setTarget();
// temp1 = _$fH(target[tarkey], temp4);
break;
case 110:
temp1 = data[--d_cursor];
setTarget();
temp1 = target[tarkey] -= temp1;
break;
case 111:
temp1 = data[--d_cursor];
temp1 = data[--d_cursor] ^ temp1;
data[d_cursor++] = temp1;
break;
}
}
function setTarget() {
let next = task[++t_cursor];
if (next <= 24) {
tarkey = data[--d_cursor];
target = data[--d_cursor];
} else if (next > 24 && next <= 27) {
logger.trace(`[no] 设置关键对象与下标:${next}`)
// temp3 = task[++t_cursor];
// tarkey = task[++t_cursor];
// target = ret[3][temp3];
debugger;
} else if (next > 27 && next <= 33) {
tarkey = task[++t_cursor];
target = ret[0];
} else if (next > 33 && next <= 37) {
task[t_cursor] = 92;
tarkey = keywords[task[++t_cursor]];
task[t_cursor] = tarkey;
target = data[--d_cursor];
} else if (next > 37 && next <= 54) {
tarkey = task[++t_cursor];
target = loop_res;
} else if (next > 54 && next <= 62) {
tarkey = task[++t_cursor];
target = global_res;
} else if (next > 62 && next <= 63) {
tarkey = task[++t_cursor];
target = ret[2];
} else if (next > 63 && next <= 92) {
tarkey = task[++t_cursor];
target = data[--d_cursor];
} else if (next > 92 && next <= 99) {
task[t_cursor] = 92;
tarkey = keycodes[task[++t_cursor]];
task[t_cursor] = tarkey;
target = data[--d_cursor];
} else if (next > 99 && next <= 104) {
logger.trace(`[no] 设置关键对象与下标:${next}`)
// temp3 = task[++t_cursor];
// tarkey = task[++t_cursor];
// target = ret[1][temp3];
debugger;
ret[2] = [ 'window', args ];
const vars = [
`${codemap.params[0]} = taskItem`,
`${codemap.params[1]} = start`,
`${codemap.params[2]} = task.length`,
`${codemap.params[3]} = ret`,
// 任务列表
`${codemap.taskarr} = taskItem.taskarr`,
// 数据数组
`${codemap.dataKey} = data`,
// 数据数组游标
`${codemap.dataIdx} = 0`,
`${codemap.ret0} = ret[0]`,
`${codemap.ret1} = ret[1]`,
`${codemap.ret2} = ret[2]`,
`${codemap.ret3} = ret[3]`,
// 全局资源
`${codemap.globalRes} = global_res`,
// 本地资源
`${codemap.loopRes} = loop_res`,
`${codemap.forcur} = start`,
`${codemap.formax} = task.length`,
...codemap.varible,
].join(', ');
eval(`var ${vars};${codemap.commonFunc}`)
for (let t_cursor = start, idx = 0; t_cursor < task.length; t_cursor++) {
idx ++;
if (typeof codemap[task[t_cursor]] !== 'string') {
logger.error(`codemap中下标${task[t_cursor]}不存在值!`)
} else {
--d_cursor;
target = data;
tarkey = d_cursor;
eval(`${codemap.forcur}=t_cursor`);
codemap[task[t_cursor]].split(';').map(it => it.trim()).forEach(c => {
try {
eval(c);
} catch(err) {
logger.error(`代码: ${c} 执行失败,当前任务:${taskItem.key}`)
debugger;
throw err;
}
})
eval(`t_cursor=${codemap.forcur}`);
}
}
return ret[5];
}

View File

@ -3,11 +3,11 @@ const gv = require('@src/handler/globalVarible');
function getLens(numarr, idx) {
const item = numarr[idx];
if ((item & gv.cp2[37]) === 0) return item;
if ((item & gv.cp2[46]) == gv.cp2[37]) return (item & gv.cp2[13]) << gv.cp2[52] | numarr[idx + 1];
if ((item & gv.cp2[36]) == gv.cp2[46]) return (item & gv.cp2[1]) << gv.cp2[2] | numarr[idx + 1] << gv.cp2[52] | numarr[idx + 2];
if ((item & gv.cp2[7]) == gv.cp2[36]) return (item & gv.cp2[31]) << gv.cp2[4] | numarr[idx + 1] << gv.cp2[2] | numarr[idx + 2] << gv.cp2[52] | numarr[idx + 3];
if ((item & gv.cp2[99]) == gv.cp2[7]) return (numarr[idx + 1] << gv.cp2[4] | numarr[idx + 2] << gv.cp2[2] | numarr[idx + 3] << gv.cp2[52] | numarr[idx + 4]) >>> 0;
if ((item & 128) === 0) return item;
if ((item & 192) == 128) return (item & 63) << 8 | numarr[idx + 1];
if ((item & 224) == 192) return (item & 31) << 16 | numarr[idx + 1] << 8 | numarr[idx + 2];
if ((item & 240) == 224) return (item & 15) << 24 | numarr[idx + 1] << 16 | numarr[idx + 2] << 8 | numarr[idx + 3];
if ((item & 248) == 240) return (numarr[idx + 1] << 24 | numarr[idx + 2] << 16 | numarr[idx + 3] << 8 | numarr[idx + 4]) >>> 0;
return item;
}

View File

@ -2,7 +2,7 @@
const gv = require('@src/handler/globalVarible');
function nummod(num) {
return Math.abs(num) % gv.cp2[52];
return Math.abs(num) % 8;
}
function one(arr) {
@ -81,11 +81,11 @@ function six(arr) {
}
module.exports = () => {
const arr = [0, 1, gv.cp2[56], gv.cp2[58], gv.cp2[19], gv.cp2[29], gv.cp2[55], gv.cp2[23]];
const arr = [0, 1, 2, 3, 4, 5, 6, 7];
[one, two, three, four, five, six].forEach(func => func(arr));
const sum = arr.reduce((ans, it, idx) => {
ans[idx % 2] += it;
return ans;
}, [0, 0]);
return sum[0] & gv.cp2[34] | (sum[1] & gv.cp2[34]) << gv.cp2[52];
return sum[0] & 255 | (sum[1] & 255) << 8;
}

View File

@ -22,5 +22,7 @@ module.exports = {
numarr2string: require('./numarr2string'),
numarrJoin: require('./numarrJoin'),
dynamicExec: require('./dynamicExec'),
numarrAlterByNumber: require('./numarrAlterByNumber'),
runTask: require('./runTask'),
}

View File

@ -9,48 +9,48 @@ function encode(cfg, val, idx, cfgnum) {
const list = cfg[idx];
const arr = [0, 0, 0, 0];
let one = val[0] ^ list[0]
, two = val[idx ? gv.cp2[58] : 1] ^ list[1]
, two = val[idx ? 3 : 1] ^ list[1]
, three = val[2] ^ list[2]
, four = val[idx ? 1 : gv.cp2[58]] ^ list[3]
, cursor = gv.cp2[19];
for (let i = 0; i < list.length / gv.cp2[19] - gv.cp2[56]; i++) {
const none = cfgnum[0][one >>> gv.cp2[4]] ^ cfgnum[1][two >> gv.cp2[2] & gv.cp2[34]] ^ cfgnum[2][three >> gv.cp2[52] & gv.cp2[34]] ^ cfgnum[3][four & gv.cp2[34]] ^ list[cursor];
const ntwo = cfgnum[0][two >>> gv.cp2[4]] ^ cfgnum[1][three >> gv.cp2[2] & gv.cp2[34]] ^ cfgnum[2][four >> gv.cp2[52] & gv.cp2[34]] ^ cfgnum[3][one & gv.cp2[34]] ^ list[cursor + 1];
const nthree = cfgnum[0][three >>> gv.cp2[4]] ^ cfgnum[1][four >> gv.cp2[2] & gv.cp2[34]] ^ cfgnum[2][one >> gv.cp2[52] & gv.cp2[34]] ^ cfgnum[3][two & gv.cp2[34]] ^ list[cursor + gv.cp2[56]];
four = cfgnum[0][four >>> gv.cp2[4]] ^ cfgnum[1][one >> gv.cp2[2] & gv.cp2[34]] ^ cfgnum[2][two >> gv.cp2[52] & gv.cp2[34]] ^ cfgnum[3][three & gv.cp2[34]] ^ list[cursor + gv.cp2[58]];
cursor += gv.cp2[19];
, four = val[idx ? 1 : 3] ^ list[3]
, cursor = 4;
for (let i = 0; i < list.length / 4 - 2; i++) {
const none = cfgnum[0][one >>> 24] ^ cfgnum[1][two >> 16 & 255] ^ cfgnum[2][three >> 8 & 255] ^ cfgnum[3][four & 255] ^ list[cursor];
const ntwo = cfgnum[0][two >>> 24] ^ cfgnum[1][three >> 16 & 255] ^ cfgnum[2][four >> 8 & 255] ^ cfgnum[3][one & 255] ^ list[cursor + 1];
const nthree = cfgnum[0][three >>> 24] ^ cfgnum[1][four >> 16 & 255] ^ cfgnum[2][one >> 8 & 255] ^ cfgnum[3][two & 255] ^ list[cursor + 2];
four = cfgnum[0][four >>> 24] ^ cfgnum[1][one >> 16 & 255] ^ cfgnum[2][two >> 8 & 255] ^ cfgnum[3][three & 255] ^ list[cursor + 3];
cursor += 4;
[one, two, three] = [none, ntwo, nthree]
}
for (let i = 0; i < gv.cp2[19]; i++) {
arr[idx ? gv.cp2[58] & -i : i] = cfgnum[4][one >>> gv.cp2[4]] << gv.cp2[4] ^ cfgnum[4][two >> gv.cp2[2] & gv.cp2[34]] << gv.cp2[2] ^ cfgnum[4][three >> gv.cp2[52] & gv.cp2[34]] << gv.cp2[52] ^ cfgnum[4][four & gv.cp2[34]] ^ list[cursor++];
for (let i = 0; i < 4; i++) {
arr[idx ? 3 & -i : i] = cfgnum[4][one >>> 24] << 24 ^ cfgnum[4][two >> 16 & 255] << 16 ^ cfgnum[4][three >> 8 & 255] << 8 ^ cfgnum[4][four & 255] ^ list[cursor++];
[one, two, three, four] = [two, three, four, one];
}
return arr;
}
function getCfg(numarr) {
const ret = combine4(numarr.length % gv.cp2[2] !== 0 ? numarrAddTime.reverse(numarr)[0] : numarr);
const ret = combine4(numarr.length % 16 !== 0 ? numarrAddTime.reverse(numarr)[0] : numarr);
const cfgnum_0_4 = gv.cfgnum[0][4];
const len = ret.length;
const arr = [];
let i, j, temp;
for (i = len, j = 1; i < gv.cp2[19] * len + gv.cp2[68]; i++) {
for (i = len, j = 1; i < 4 * len + 28; i++) {
temp = ret[i - 1];
if (i % len === 0 || len === gv.cp2[52] && i % len === gv.cp2[19]) {
temp = cfgnum_0_4[temp >>> gv.cp2[4]] << gv.cp2[4] ^ cfgnum_0_4[temp >> gv.cp2[2] & gv.cp2[34]] << gv.cp2[2] ^ cfgnum_0_4[temp >> gv.cp2[52] & gv.cp2[34]] << gv.cp2[52] ^ cfgnum_0_4[temp & gv.cp2[34]];
if (i % len === 0 || len === 8 && i % len === 4) {
temp = cfgnum_0_4[temp >>> 24] << 24 ^ cfgnum_0_4[temp >> 16 & 255] << 16 ^ cfgnum_0_4[temp >> 8 & 255] << 8 ^ cfgnum_0_4[temp & 255];
if (i % len === 0) {
temp = temp << gv.cp2[52] ^ temp >>> gv.cp2[4] ^ j << gv.cp2[4];
j = j << 1 ^ (j >> gv.cp2[23]) * gv.cp2[93];
temp = temp << 8 ^ temp >>> 24 ^ j << 24;
j = j << 1 ^ (j >> 7) * 283;
}
}
ret[i] = ret[i - len] ^ temp;
}
for (j = 0; i; j++, i--) {
temp = ret[j & gv.cp2[58] ? i : i - gv.cp2[19]];
if (i <= gv.cp2[19] || j < gv.cp2[19]) {
temp = ret[j & 3 ? i : i - 4];
if (i <= 4 || j < 4) {
arr[j] = temp;
} else {
arr[j] = gv.cfgnum[1][0][cfgnum_0_4[temp >>> gv.cp2[4]]] ^ gv.cfgnum[1][1][cfgnum_0_4[temp >> gv.cp2[2] & gv.cp2[34]]] ^ gv.cfgnum[1][2][cfgnum_0_4[temp >> gv.cp2[52] & gv.cp2[34]]] ^ gv.cfgnum[1][3][cfgnum_0_4[temp & gv.cp2[34]]];
arr[j] = gv.cfgnum[1][0][cfgnum_0_4[temp >>> 24]] ^ gv.cfgnum[1][1][cfgnum_0_4[temp >> 16 & 255]] ^ gv.cfgnum[1][2][cfgnum_0_4[temp >> 8 & 255]] ^ gv.cfgnum[1][3][cfgnum_0_4[temp & 255]];
}
}
return [ret, arr];
@ -59,15 +59,15 @@ function getCfg(numarr) {
function encryptMode1(valarr, keyarr, flag = 1) {
const cfg = getCfg(keyarr);
var _$iv, _$j7, _$kb, _$ka, _$dV, _$du, _$jb;
const max = Math.floor(valarr.length / gv.cp2[2]) + 1;
const max = Math.floor(valarr.length / 16) + 1;
let ans = [], arr;
const fill = gv.cp2[2] - valarr.length % gv.cp2[2];
const fill = 16 - valarr.length % 16;
if (flag) {
ans = arr = new Array(4).fill(gv.cp2[17]).map(it => Math.floor(Math.random() * it));
ans = arr = new Array(4).fill(4294967295).map(it => Math.floor(Math.random() * it));
}
const copyarr = numToNumarr4.reverse_sign([...valarr, ...new Array(fill).fill(fill)]);
for (let i = 0; i < max; ) {
let current = copyarr.slice(i << gv.cp2[56], ++i << gv.cp2[56]);
let current = copyarr.slice(i << 2, ++i << 2);
if (arr) {
current = [0, 1, 2, 3].map(it => current[it] ^ arr[it]);
}
@ -85,11 +85,11 @@ function encryptMode2(valarr, keyarr, flag = 1) {
let arrcom = combine4(valarr);
let arrsub = [];
if (flag) {
arrsub = arrcom.slice(0, gv.cp2[19]);
arrcom = arrcom.slice(gv.cp2[19]);
arrsub = arrcom.slice(0, 4);
arrcom = arrcom.slice(4);
}
for (let i = 0; i < arrcom.length / gv.cp2[19]; ) {
const next = arrcom.slice(i << gv.cp2[56], ++i << gv.cp2[56]);
for (let i = 0; i < arrcom.length / 4; ) {
const next = arrcom.slice(i << 2, ++i << 2);
let val = encode(cfg, next, 1, gv.cfgnum[1]);
if (arrsub.length) {
val = _zip(val, arrsub).map(([a, b]) => a ^ b);

View File

@ -4,11 +4,11 @@ const gv = require('@src/handler/globalVarible');
module.exports = function (num) {
if (typeof num !== 'number' || num < 0) {
num = 0;
} else if (num > gv.cp2[25]) {
num = gv.cp2[25];
} else if (num > 65535) {
num = 65535;
}
return [
num >> gv.cp2[52],
num & gv.cp2[34]
num >> 8,
num & 255
]
}

View File

@ -11,10 +11,10 @@ module.exports = function (num) {
}
if (typeof num !== 'number') num = 0;
return [
num >> gv.cp2[4] & gv.cp2[34],
num >> gv.cp2[2] & gv.cp2[34],
num >> gv.cp2[52] & gv.cp2[34],
num & gv.cp2[34]
num >> 24 & 255,
num >> 16 & 255,
num >> 8 & 255,
num & 255
];
}
@ -24,7 +24,7 @@ module.exports.reverse = function (numarr) {
if (numarr.length % 4 !== 0) throw new Error('使用numToNumarr4.reverse方法时传入的数字数组必须是4的倍数');
return _chunk(numarr, 4).map(it => module.exports.reverse(it));
}
return (numarr[0] << gv.cp2[4] | numarr[1] << gv.cp2[2] | numarr[2] << gv.cp2[52] | numarr[3]) >>> 0;
return (numarr[0] << 24 | numarr[1] << 16 | numarr[2] << 8 | numarr[3]) >>> 0;
}
module.exports.reverse_sign = function (numarr) {
@ -33,5 +33,5 @@ module.exports.reverse_sign = function (numarr) {
if (numarr.length % 4 !== 0) throw new Error('使用numToNumarr4.reverse方法时传入的数字数组必须是4的倍数');
return _chunk(numarr, 4).map(it => module.exports.reverse_sign(it));
}
return (numarr[0] << gv.cp2[4] | numarr[1] << gv.cp2[2] | numarr[2] << gv.cp2[52] | numarr[3]);
return (numarr[0] << 24 | numarr[1] << 16 | numarr[2] << 8 | numarr[3]);
}

View File

@ -3,16 +3,16 @@ const gv = require('@src/handler/globalVarible');
module.exports = function (num) {
if (typeof num !== 'number' || num < 0) num = 0;
const one = num / gv.cp2[16];
const two = num % gv.cp2[16];
const one = num / 4294967296;
const two = num % 4294967296;
return [
one >> gv.cp2[4] & gv.cp2[34],
one >> gv.cp2[2] & gv.cp2[34],
one >> gv.cp2[52] & gv.cp2[34],
one & gv.cp2[34],
two >> gv.cp2[4] & gv.cp2[34],
two >> gv.cp2[2] & gv.cp2[34],
two >> gv.cp2[52] & gv.cp2[34],
two & gv.cp2[34],
one >> 24 & 255,
one >> 16 & 255,
one >> 8 & 255,
one & 255,
two >> 24 & 255,
two >> 16 & 255,
two >> 8 & 255,
two & 255,
]
}

View File

@ -6,26 +6,26 @@ module.exports = function(numarr, keys) {
if (typeof numarr === 'string') {
numarr = string2ascii(numarr);
}
keys = keys || gv.cp0_96(7, 41).split('');
keys = keys || gv.basestr.split('');
let idx = 0;
const ans = [];
while (idx < numarr.length - gv.cp2[56]) {
while (idx < numarr.length - 2) {
const [one, two, three] = [numarr[idx], numarr[idx + 1], numarr[idx + 2]];
idx += 3;
ans.push(
keys[one >> gv.cp2[56]],
keys[(one & gv.cp2[58]) << gv.cp2[19] | two >> gv.cp2[19]],
keys[(two & gv.cp2[31]) << gv.cp2[56] | three >> gv.cp2[55]],
keys[three & gv.cp2[13]],
keys[one >> 2],
keys[(one & 3) << 4 | two >> 4],
keys[(two & 15) << 2 | three >> 6],
keys[three & 63],
);
}
if (idx < numarr.length) {
ans.push(
keys[numarr[idx] >> gv.cp2[56]],
keys[(numarr[idx + 1] & gv.cp2[58]) << gv.cp2[19] | numarr[idx + 1] >> gv.cp2[19]],
keys[numarr[idx] >> 2],
keys[(numarr[idx + 1] & 3) << 4 | numarr[idx + 1] >> 4],
)
if (numarr[idx + 1] !== undefined) {
ans.push(keys[(numarr[idx + 1] & gv.cp2[31]) << gv.cp2[56]])
ans.push(keys[(numarr[idx + 1] & 15) << 2])
}
}
return ans.join('');

View File

@ -4,7 +4,7 @@ const numToNumarr4 = require('./numToNumarr4');
module.exports = function(numarr, time) {
// time为时间戳除以1000后向上取整如果不传则取当前时间戳
const ele = Math.ceil(Math.random() * gv.cp2[30]);
const ele = Math.ceil(Math.random() * 256);
const now = time || Math.floor(new Date().getTime() / 1000);
const arr = [...numarr, ...numToNumarr4(now)].map(it => it ^ ele);
arr.push(ele);

View File

@ -0,0 +1,10 @@
// 根据uid修改数字数组
const gv = require('@src/handler/globalVarible');
module.exports = function (numarr, start, num = 0) {
if (typeof num !== 'number') num = 0;
numarr[start] = num >> 24 & 255;
numarr[start + 1] = num >> 16 & 255;
numarr[start + 2] = num >> 8 & 255;
numarr[start + 3] = num & 255;
}

View File

@ -2,17 +2,17 @@ const gv = require('@src/handler/globalVarible');
function getTree() {
let arr = [];
for (let i = 1; i < gv.cp2[34]; i++) {
for (let i = 1; i < 255; i++) {
arr.push({
total: 1,
idx: i
});
}
arr.push({
total: gv.cp2[55],
idx: gv.cp2[34]
total: 6,
idx: 255
}, {
total: gv.cp2[49],
total: 45,
idx: 0
}
);
@ -26,8 +26,8 @@ function getTree() {
arr.push(item);
}
while (arr.length > 1) {
const [one, two] = arr.slice(0, gv.cp2[56]);
arr = arr.slice(gv.cp2[56]);
const [one, two] = arr.slice(0, 2);
arr = arr.slice(2);
parse({
total: one.total + two.total,
first: one,
@ -39,8 +39,8 @@ function getTree() {
function getKey(arr) {
for (let idx in arr) {
if (arr[idx].val >= gv.cp2[52]) {
return arr[idx].key >> arr[idx].val - gv.cp2[52];
if (arr[idx].val >= 8) {
return arr[idx].key >> arr[idx].val - 8;
}
}
}
@ -74,14 +74,14 @@ module.exports = function (numarr) {
const cfg = encryptConfig[0][numarr[i]];
one = one << cfg.val | cfg.key;
two += cfg.val;
while (two >= gv.cp2[52]) {
ans.push(one >> two - gv.cp2[52]);
one &= ~(gv.cp2[34] << two - gv.cp2[52]);
two -= gv.cp2[52];
while (two >= 8) {
ans.push(one >> two - 8);
one &= ~(255 << two - 8);
two -= 8;
}
}
if (two > 0) {
ans.push(one << gv.cp2[52] - two | encryptConfig[1] >> two);
ans.push(one << 8 - two | encryptConfig[1] >> two);
}
return ans;
}

View File

@ -1,7 +1,7 @@
const gv = require('@src/handler/globalVarible');
const _sum = require('lodash/sum');
exports.execNumberByTime = function (times = gv.cp2[58]) {
exports.execNumberByTime = function (times = 3) {
// 指定时间内的代码循环次数,相比于浏览器瑞数环境删减代码较多, 因此浏览器环境与nodejs环境执行存在较大偏差该方法不建议使用预估返回值为600-1000
if (typeof times !== 'number') return;
const start = new Date();
@ -10,14 +10,14 @@ exports.execNumberByTime = function (times = gv.cp2[58]) {
return i;
}
exports.execRandomByNumber = function (nums = gv.cp2[108]) {
exports.execRandomByNumber = function (nums = 98) {
// 指定次数的随机数取平均值后四舍五入
if (typeof nums !== 'number') return;
const arr = []
for (let i = 0; i < nums; i++) arr.push(Math.random());
const avg = _sum(arr) / nums;
return [
avg * gv.cp2[28],
_sum(arr.map(it => Math.pow(it - avg, gv.cp2[56]))) / nums * gv.cp2[28],
avg * 100,
_sum(arr.map(it => Math.pow(it - avg, 2))) / nums * 100,
].map(it => Math.round(it));
}

View File

@ -0,0 +1,45 @@
// 直接通过动态代码执行来运行任务
// 该方法并未完全还原,谨慎使用
const gv = require('@src/handler/globalVarible');
const dynamicExec = require('./dynamicExec');
const custask = require('../task');
const error = require('@utils/error');
const logger = require('@utils/logger');
module.exports = function(taskid, args, allowTask) {
// taskid为任务idallowTask为允许执行的任务
const task = gv.r2mka(taskid);
if (!task) {
error(`任务未找到`, { taskid });
}
const global_res = new Proxy({}, {
get(target, property, receiver) {
// 由于每个版本下标都会变在解析cd值生成8位偏移数的时候只用到了cp2数组因此这里只返回cp2需要注意
logger.debug(`global_res 获取下标: ${property}`);
return gv.cp2;
}
})
const loop_res = new Proxy([], {
get(target, key, receiver) {
const child = gv.r2mka().child_one;
if (Number(key) < child.length) {
const current = child[key];
if (!key) return current;
return (...params) => {
if (custask[current.key]) {
// 自定义任务
return custask[current.key](...params);
}
if (allowTask && !allowTask[key]) {
error('当前任务未在允许列表!', { key: current.key });
}
return dynamicExec(current, 0, params, loop_res, global_res);
}
}
if (gv.config.offsetConst[key]) return gv.config.offsetConst[key];
error('loop_res取值未找到', { key });
}
})
return dynamicExec(task, 0, args, loop_res, global_res);
}

View File

@ -0,0 +1,28 @@
const gv = require('@src/handler/globalVarible');
function (text) {
let one, two, three, four, idx = 0, dkey = gv.decryptKeys[5];
const flag = dkey[text.charCodeAt(idx++)];
if (flag <= 80) return flag;
if (flag == 81) {
return dkey[text.charCodeAt(idx++)] + 80;
}
if (flag == 82) {
one = dkey[text.charCodeAt(idx++)];
two = dkey[text.charCodeAt(idx++)];
return one + two * 86 + 165;
}
if (flag == 83) {
one = dkey[text.charCodeAt(idx++)];
two = dkey[text.charCodeAt(idx++)];
three = dkey[text.charCodeAt(idx++)];
return one + two * 86 + three * 86 * 86 + 7560;
}
if (flag == 84) {
one = dkey[text.charCodeAt(idx++)];
two = dkey[text.charCodeAt(idx++)];
three = dkey[text.charCodeAt(idx++)];
four = dkey[text.charCodeAt(idx++)];
return one + two * 86 + three * 86 * 86 + four * 86 * 86 * 86 + 643615;
}
}

View File

@ -8,9 +8,9 @@ function str2code(str) {
module.exports = function (numarr) {
if (typeof numarr === 'string') numarr = str2code(numarr);
let val = 0 ^ gv.cp2[41];
let val = 0 ^ -1;
for (let i = 0; i < numarr.length; ) {
val = val >>> gv.cp2[52] ^ gv.bignum[(val ^ numarr[i++]) & gv.cp2[34]];
val = val >>> 8 ^ gv.bignum[(val ^ numarr[i++]) & 255];
}
return (val ^ gv.cp2[41]) >>> 0;
return (val ^ -1) >>> 0;
}

View File

@ -0,0 +1,67 @@
const gv = require('@src/handler/globalVarible');
function makeCfgnum() {
const arr1 = [[], [], [], [], []];
const arr2 = [[], [], [], [], []];
const arr1_4 = arr1[4];
const arr2_4 = arr2[4];
const one = [];
const two = [];
let i, j, temp;
for (i = 0; i < 256; i++) {
two[(one[i] = i << 1 ^ (i >> 7) * 283) ^ i] = i;
}
for (i = j = 0; !arr1_4[i]; i ^= one[i] || 1, j = two[j] || 1) {
temp = j ^ j << 1 ^ j << 2 ^ j << 3 ^ j << 4;
temp = temp >> 8 ^ temp & 255 ^ 99;
arr1_4[i] = temp;
arr2_4[temp] = i;
}
for (i = 0; i < 256; i++) {
arr2_4[arr1_4[i]] = i;
}
for (i = 0; i < 256; i++) {
let ele1 = one[one[one[i]]] * 16843009 ^ one[one[i]] * 65537 ^ one[i] * 257 ^ i * 16843008;
let ele2 = one[arr1_4[i]] * 257 ^ arr1_4[i] * 16843008;
for (j = 0; j < 4; j++) {
arr1[j][i] = ele2 = ele2 << 24 ^ ele2 >>> 8;
arr2[j][arr1_4[i]] = ele1 = ele1 << 24 ^ ele1 >>> 8;
}
}
for (i = 0; i < 5; i++) {
arr1[i] = arr1[i].slice(0);
arr2[i] = arr2[i].slice(0);
}
return [arr1, arr2]
}
function makeBignum() {
const arr = [];
for (let i = 0; i < 256; i++) {
let item = i;
for (_$iv = 0; _$iv < 8; _$iv++) {
item = item & 1 ? 3988292384 ^ item >>> 1 : item >>> 1;
}
arr[i] = item;
}
return arr;
}
function makeDecryptKeys() {
return gv.basestr.split('').reduce((ans, key, idx) => {
const code = key.charCodeAt()
ans[0][code] = idx << 2;
ans[1][code] = idx >> 4;
ans[2][code] = (idx & 15) << 4;
ans[3][code] = idx >> 2;
ans[4][code] = (idx & 3) << 6;
ans[5][code] = idx;
return ans
}, [{}, {}, {}, {}, {}, { ...new Array(255 + 1).fill(-1) }]);
}
exports.init = function() {
gv._setAttr('bignum', makeBignum());
gv._setAttr('cfgnum', makeCfgnum());
gv._setAttr('decryptKeys', makeDecryptKeys());
}

View File

@ -8,8 +8,9 @@ function init(ts, r2mkaText) {
gv._setAttr('ts', ts);
require('./r2mka').init(r2mkaText);
require('./tscp').init();
require('./constData').init(); // 常量数据初始化依赖于cp值因此要放在cp后面
require('./tscd').init();
require('./bignum').init();
require('./meta').init();
logger.debug(`globalVarible完成初始化用时${new Date().getTime() - startTime}ms`);
}

View File

@ -1,5 +1,4 @@
const gv = require('../globalVarible');
const gt3 = require('@src/immutext/').globalText3;
const logger = require('@utils/logger');
function gtHandler(str, curr) {
@ -57,7 +56,8 @@ const parse = (() => {
}
})();
exports.parse = function(str = gt3) {
exports.parse = function(str) {
if (!str) str = gv.config.immucfg.globalText3;
const r2mka_len = 'r2mka'.length;
const flag = str.charAt(r2mka_len) === '1';
const gt = gtHandler(str, r2mka_len + 1);
@ -86,6 +86,6 @@ exports.parse = function(str = gt3) {
};
exports.init = function(r2mkaText) {
gv._setAttr('r2mka', exports.parse(r2mkaText || gt3));
gv._setAttr('r2mka', exports.parse(r2mkaText || gv.config.immucfg.globalText3));
logger.debug('头r2mka标识字符串完成解析!')
}

View File

@ -1,7 +1,12 @@
const gv = require('@src/handler/globalVarible');
// 预期任务作用,实际还没有用到,需要多版本对比
const expectTask = {
'0>one>71>one>4>one>3-344': '计算阶乘'
}
module.exports = {
'0>one>21-23': (num) => {
return Math.abs(num) % gv.cp2[52];
}
return Math.abs(num) % 8;
},
}

View File

@ -3,16 +3,16 @@ const gv = require('../globalVarible');
const decrypt = require('./common/decrypt');
const logger = require('@utils/logger');
const numToNumarr4 = require('./common/numToNumarr4');
const dynamicExec = require('./common/dynamicExec');
const runTask = require('./common/runTask');
const custask = require('./task');
const error = require('@utils/error');
function getValMaps() {
let uid = gv.ts.cp[3];
const ans = [];
for (let i = 0; i < gv.cp2[19]; i++) {
uid = gv.cp2[174] * (uid & gv.cp2[25]) + gv.cp2[135]
ans.push(uid)
for (let i = 0; i < 4; i++) {
uid = 15679 * (uid & 65535) + 2531011;
ans.push(uid);
}
return numToNumarr4(ans);
}
@ -22,8 +22,8 @@ function parse(arr) {
const valMap = getValMaps();
let idx = 4;
do {
idx += gv.cp2[2];
const mod = idx % (len - idx > gv.cp2[2] ? gv.cp2[2] : len - idx);
idx += 16;
const mod = idx % (len - idx > 16 ? 16 : len - idx);
if (mod + idx < arr.length) {
arr[mod + idx] ^= valMap[mod];
}
@ -41,42 +41,16 @@ function getTaskarr(arr, idx, ans = {}) {
return ans;
}
function getOffset(arr) {
const taskMap = getTaskarr(arr, arr[3]);
const l81 = gv.r2mka("0-0").taskarr[42] + gv.cp2[56];
const l82 = gv.cp0_96(1, gv.r2mka("0-0").taskarr[57]).charCodeAt() + l81;
const l83 = l82 * l81;
const global_res = {
59: gv.cp2,
};
const loop_res = gv.r2mka().child_one.map((it, idx) => {
if (!it) return it;
return (...params) => {
if (taskMap[idx]) {
return dynamicExec(it, 0, params, loop_res, global_res);
}
if (custask[it.key]) {
return custask[it.key](...params);
}
error(1000, { key: it.key }); // 任务方法未适配终止方法运行
}
})
loop_res[81] = l81;
loop_res[82] = l82;
loop_res[83] = l83;
return dynamicExec(gv.r2mka('0>one>22-24'), 0, undefined, loop_res, global_res);
}
exports.init = function() {
const cdArr = decrypt(gv.ts.cd);
const start = gv.r2mka('0>one>23-25').taskarr[9] + 2;
const end = (cdArr[0] << gv.cp2[52] | cdArr[1]) + start;
const one = parse(cdArr.slice(start, end)); // arr127
const offset = getOffset(one);
const end = (cdArr[0] << 8 | cdArr[1]) + start;
const one = parse(cdArr.slice(start, end));
const offset = runTask('0>one>22-24', [], getTaskarr(one, one[3])); // 获取解密用偏移值数组
gv._setAttr('dynamicTaskOffset', offset);
gv._setAttr('dynamicTask', getTaskarr(one, one[3]));
const ans = cdArr.slice(end).map((item, idx) => { // arr1575
return item ^ offset[idx % gv.cp2[52]];
const ans = cdArr.slice(end).map((item, idx) => {
return item ^ offset[idx % 8];
})
const keys = []
for (let i = 0, op = 1; i < ans[0]; i ++) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +0,0 @@
const globalText = require('./global');
const $_ts = require('./$_ts');
module.exports = {
...globalText,
$_ts,
}

27
src/makeCodeHigh.js Normal file
View File

@ -0,0 +1,27 @@
const CoderHigh = require('./handler/CoderHigh');
const paths = require('@utils/paths');
const fs = require('fs');
const logger = require('@utils/logger');
const Coder = require('./handler/Coder');
const Cookie = require('./handler/Cookie');
const unescape = require('@utils/unescape');
const gv = require('@src/handler/globalVarible');
function parseR2mka(text) {
const start = text.indexOf('"') + 1;
const end = text.lastIndexOf('"') - 2;
return unescape(text.substr(start, end));
}
module.exports = function (ts, immucfg) {
console.log('还原更多加密文件如app.js等作者开发中可关注微信订阅号`码功`获取项目更新推送!');
return
gv._setAttr('_ts', ts);
const startTime = new Date().getTime();
const coder = new Coder(ts, immucfg);
const { code, $_ts } = coder.run();
const r2mkaText = parseR2mka(coder.r2mkaText);
const cookie = new Cookie($_ts, r2mkaText).run();
return cookie;
}

BIN
static/keynameNum1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
static/keynameNum2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -3,8 +3,10 @@ const Coder = require('@src/handler/Coder');
const paths = require('@utils/paths');
const fs = require('fs');
const _isEqual = require('lodash/isEqual');
const gv = require('@src/handler/globalVarible');
test('make dynamic code by example 1', () => {
test('版本1动态代码生成比对', () => {
gv._setAttr('version', 1);
const codePath = paths.exampleResolve('codes', '1-code.js');
const tsPath = paths.exampleResolve('codes', '1-$_ts.json');
const tsFullPath = paths.exampleResolve('codes', '1-$_ts-full.json');
@ -17,25 +19,7 @@ test('make dynamic code by example 1', () => {
$_ts.cp[4] = tsFull.cp[4] = 0; // 运行时间调整一致
tsFull.lcd = tsFull.nsd = undefined; // JSON.stringify时丢失的字段补齐
delete tsFull.cp[5]; // JSON.stringify时将数组空元素用null填充还原
expect(code).toBe(tarCode);
expect(_isEqual($_ts, tsFull)).toBe(true);
});
test('make dynamic code by example 2', () => {
const codePath = paths.exampleResolve('codes', '2-code.js');
const tsPath = paths.exampleResolve('codes', '2-$_ts.json');
const tsFullPath = paths.exampleResolve('codes', '2-$_ts-full.json');
const ts = JSON.parse(fs.readFileSync(tsPath, 'utf8'));
const tarCode = fs.readFileSync(codePath, 'utf8');
const tsFull = JSON.parse(fs.readFileSync(tsFullPath, 'utf8'));
const coder = new Coder(ts);
const { code, $_ts } = coder.run();
$_ts.cp[4] = tsFull.cp[4] = 0; // 运行时间调整一致
tsFull.lcd = tsFull.nsd = undefined; // JSON.stringify时丢失的字段补齐
delete tsFull.cp[5]; // JSON.stringify时将数组空元素用null填充还原
expect(code).toBe(tarCode);
expect(code.trim()).toBe(tarCode.trim());
expect(_isEqual($_ts, tsFull)).toBe(true);
});

24
test/coder_v2.test.js Normal file
View File

@ -0,0 +1,24 @@
// require('module-alias/register');
const Coder = require('@src/handler/Coder');
const paths = require('@utils/paths');
const fs = require('fs');
const _isEqual = require('lodash/isEqual');
const gv = require('@src/handler/globalVarible');
test('版本2动态代码生成比对', () => {
gv._setAttr('version', 2);
const codePath = paths.exampleResolve('codes', '2-code.js');
const tsPath = paths.exampleResolve('codes', '2-$_ts.json');
const tsFullPath = paths.exampleResolve('codes', '2-$_ts-full.json');
const ts = JSON.parse(fs.readFileSync(tsPath, 'utf8'));
const tarCode = fs.readFileSync(codePath, 'utf8');
const tsFull = JSON.parse(fs.readFileSync(tsFullPath, 'utf8'));
const coder = new Coder(ts);
const { code, $_ts } = coder.run();
$_ts.cp[4] = tsFull.cp[4] = 0; // 运行时间调整一致
tsFull.lcd = tsFull.nsd = undefined; // JSON.stringify时丢失的字段补齐
delete tsFull.cp[5]; // JSON.stringify时将数组空元素用null填充还原
expect(code.trim()).toBe(tarCode.trim());
expect(_isEqual($_ts, tsFull)).toBe(true);
});

View File

@ -1,21 +1,5 @@
const gv = require('../utils/initGv')();
const gv = require('../utils/initGv')(1);
const { main, swap4, swap2, hexnum, stringReverse, init } = gv.utils;
/*
setData('G_$cc', cp0[0]);
setData('G_$ia', cp0[1]);
setData('G_$ga', cp0[2]);
setData('G_$_7', cp0[3]);
setData('G_$_3', cp0[4]);
setData('G_$jY', cp0[5]);
setData('G_$ad', cp0[6]);
setData('G_$bJ', cp0[7]);
setData('G_$eh', cp0[8]);
setData('G_$bv', cp0[9]);
setData('G_$bO', cp0[10]);
setData('G_$_x', cp0[11]);
setData('G_$dL', cp0[12]);
setData('G_$bn', cp0[13]);
*/
const valueMap = {
'visibilityState': main(gv.cp0_96(6, 69)).join(),

View File

@ -1,4 +1,4 @@
const gv = require('../utils/initGv')();
const gv = require('../utils/initGv')(1);
const {
main,
swap4,

View File

@ -1,4 +1,4 @@
const gv = require('../utils/initGv')();
const gv = require('../utils/initGv')(1);
const { ascii2string } = gv.utils;
const valueMap = {

View File

@ -10,5 +10,5 @@ module.exports = function(type, data = {}) {
Object.assign(data, gv._getAttr('_ts'));
data.errType = type;
logger.fatal(`(${type})程序出错啦请将该段报错文本贴到issue中${JSON.stringify(data)}`);
throw new Error(errorMap[type || 9999])
throw new Error(errorMap[type] || type);
}

23
utils/findFullString.js Normal file
View File

@ -0,0 +1,23 @@
const unescape = require('./unescape');
module.exports = function findFullString(text, sub) {
const idx = text.indexOf(sub);
if (idx === -1) throw new Error(`文本中未找到"${sub}"子字符串`);
if (text.indexOf(sub, idx + sub.length) > -1) throw new Error(`文本中存在多处"${sub}"子字符串`);
let start = idx
, end = idx + sub.length
, startIdx
, endIdx;
do {
if (startIdx <= 0 || endIdx >= text.length - 1) return;
startIdx === undefined && start--;
endIdx === undefined && end++;
if (startIdx === undefined && text[start] === '"' && text[start - 1] !== '\\') {
startIdx = start;
}
if (endIdx === undefined && text[end] === '"' && text[end - 1] !== '\\') {
endIdx = end;
}
} while (startIdx === undefined || endIdx === undefined);
return unescape(text.slice(startIdx + 1, endIdx));
}

36
utils/getCode.js Normal file
View File

@ -0,0 +1,36 @@
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
const request = require('request-promise');
const cheerio = require('cheerio');
const isValidUrl = require('./isValidUrl');
const _get = require('lodash/get');
const urlresolve = require('url').resolve;
function addRequestHead(uri) {
return {
// proxy: 'http://127.0.0.1:7777',
// gzip: true
uri,
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
resolveWithFullResponse: true,
simple: false,
}
}
module.exports = async function getCode(url) {
if (!isValidUrl(url)) throw new Error('输入链接不正确');
const res = await request(addRequestHead(url));
const $ = cheerio.load(res.body);
const scripts = [...$('script[r=m]')]
const tsscript = scripts.map(ele => $(ele).text()).filter(text => text.includes('$_ts.nsd') && text.includes('$_ts.cd'));
if (!tsscript.length) throw new Error(`${res.body}\n错误链接返回结果未找到cd或nsd, 请检查!`);
const $_ts = Function('window', tsscript[0] + 'return $_ts')({});
$_ts.metaContent = _get($('meta[r=m]'), '0.attribs.content');
const checkSrc = (src) => src?.split('.').pop() === 'js' ? src : undefined;
const remotes = scripts.map(it => checkSrc(it.attribs.src)).filter(Boolean);
if (!remotes.length) throw new Error('未找到js外链无法提取配置文本请检查!');
for(let src of remotes) {
const jscode = await request(addRequestHead(urlresolve(url, src)));
if (jscode.body.includes('r2mKa')) return { $_ts, jscode: jscode.body, html: res.body, url };
}
throw new Error('js外链中没有瑞数的代码文件');
}

View File

@ -1,3 +1,5 @@
exports.logger = require('./logger');
exports.isValidUrl = require('./isValidUrl');
exports.paths = require('./paths');
exports.getCode = require('./getCode');
exports.findFullString = require('./findFullString');

View File

@ -2,11 +2,15 @@ const paths = require('@utils/paths');
const fs = require('fs');
const { init } = require('@src/handler/parser/');
const logger = require('./logger');
const gv = require('@src/handler/globalVarible');
module.exports = function(filepath) {
if (!filepath) filepath = paths.exampleResolve('codes', "1-$_ts-full.json")
if (typeof filepath !== 'string') {
if (typeof filepath === 'number') gv._setAttr('version', filepath);
filepath = paths.exampleResolve('codes', `${gv.version}-$_ts-full.json`)
}
if (!fs.existsSync(filepath)) throw new Error(`输入文件不存在: ${filepath}`);
logger.debug(`初始化GlobalVarible变量$_ts配置文件${filepath}`);
init(JSON.parse(fs.readFileSync(filepath, 'utf8')));
return require('@src/handler/globalVarible');
return gv;
};

View File

@ -1,7 +1,23 @@
const paths = require('./paths');
const pkg = require(paths.package);
const log4js = require('log4js');
const logger = require('log4js').getLogger(pkg.name);
log4js.configure({
appenders: {
out: {
type: 'stdout',
layout: {
type: 'pattern',
pattern: '%[%p %c -%] %m'
}
}
},
categories: {
default: { appenders: ['out'], level: 'info' }
}
});
const logger = log4js.getLogger(pkg.name);
logger.level = process.env.loglevel || pkg.logLevel;
module.exports = logger;