Fyoung密码算法

Fyoung密码算法

Fyoung密码算法

前言

Fyoung最近在部分学校更新了新的认证方式,貌似认证变简单了(使用的网页认证,没有什么加密),但是加强了检测,一旦检测到共享网络,就会封号一段时间,需要联系客服解封。

但博主的学校没有更新,依然使用的旧的认证方式,对于新飞Young还得靠其他大佬的破解,不过这个算法还是很有意思的,所以就记录一下。

当然本文只是记录了密码的算法,对于参数、日志等算法想必大家也不需要,所以就不记录了。

同时也在我的 GitHub 上开源了这个算法的实现,欢迎大家Star。

如果有需要参数、日志等的,可以私我,我会尽量提供。

算法

const md5 = require("js-md5");

const DateEnum = [

"5084972163",

"9801567243",

"7286059143",

"1850394726",

"1462578093",

"5042936178",

"0145937682",

"0964238571",

"3497651802",

"9125780643",

"8634972150",

"5924673801",

"8274053169",

"5841792063",

"2469385701",

"8205349671",

"7429516038",

"3769458021",

"5862370914",

"8529364170",

"7936082154",

"5786241930",

"0728643951",

"9418360257",

"5093287146",

"5647830192",

"3986145207",

"0942587136",

"4357069128",

"0956723814",

"1502796384",

];

class MyEncrypt {

CounterByteArr = [];

keyToByteArr = [];

byteArrLenth = 0;

constructor(byteArr = []) {

if (byteArr.length > 0 && byteArr.length < 256) {

this.byteArrLenth = byteArr.length;

for (let i = 0; i < 256; i++) {

this.CounterByteArr[i] = i <= 127 ? i : i - 256;

this.keyToByteArr[i] = byteArr[i % this.byteArrLenth];

}

let i = 0;

for (let j = 0; j < 256; j++) {

i = (i + this.CounterByteArr[j] + this.keyToByteArr[j]) & 255;

let temp = this.CounterByteArr[i];

this.CounterByteArr[i] = this.CounterByteArr[j];

this.CounterByteArr[j] = temp;

}

}

}

static encryptPassword(key, password) {

let strCharArr = this.strToCharArr(key);

let this_instance = new MyEncrypt(strCharArr);

let passwordToByte = this.strToUtf8Bytes(password);

let password_bytes = this_instance.swapCounterXORPass(passwordToByte);

let crypt_pass = this_instance.encodeChangePass(password_bytes);

return crypt_pass.length === 32 ? crypt_pass.substring(8, 24) : crypt_pass;

}

static charToInt(char) {

switch (char) {

case "0":

return 0;

case "1":

return 1;

case "2":

return 2;

case "3":

return 3;

case "4":

return 4;

case "5":

return 5;

case "6":

return 6;

case "7":

return 7;

case "8":

return 8;

case "9":

return 9;

case "A":

return 10;

case "B":

return 11;

case "c":

return 12;

case "D":

return 13;

case "E":

return 14;

case "F":

return 15;

default:

return 0;

}

}

static strToCharArr(str) {

let res = [];

for (let i = 0; i < str.length; i++) {

res.push(this.charToInt(str.charAt(i)));

}

return res;

}

static strToUtf8Bytes(str) {

const utf8 = [];

for (let ii = 0; ii < str.length; ii++) {

let charCode = str.charCodeAt(ii);

if (charCode < 0x80) utf8.push(charCode);

else if (charCode < 0x800) {

utf8.push(0xc0 | (charCode >> 6), 0x80 | (charCode & 0x3f));

} else if (charCode < 0xd800 || charCode >= 0xe000) {

utf8.push(

0xe0 | (charCode >> 12),

0x80 | ((charCode >> 6) & 0x3f),

0x80 | (charCode & 0x3f)

);

} else {

ii++;

// Surrogate pair:

// UTF-16 encodes 0x10000-0x10FFFF by subtracting 0x10000 and

// splitting the 20 bits of 0x0-0xFFFFF into two halves

charCode =

0x10000 + (((charCode & 0x3ff) << 10) | (str.charCodeAt(ii) & 0x3ff));

utf8.push(

0xf0 | (charCode >> 18),

0x80 | ((charCode >> 12) & 0x3f),

0x80 | ((charCode >> 6) & 0x3f),

0x80 | (charCode & 0x3f)

);

}

}

//兼容汉字,ASCII码表最大的值为127,大于127的值为特殊字符

for (let jj = 0; jj < utf8.length; jj++) {

var code = utf8[jj];

if (code > 127) {

utf8[jj] = code - 256;

}

}

return utf8;

}

swapCounterXORPass(strBytes) {

let res = [];

let i = 0,

j = 0;

for (let k = 0; k < strBytes.length; k++) {

i = (i + 1) & 255;

j = (j + this.CounterByteArr[i]) & 255;

// 交换值

let temp = this.CounterByteArr[j];

this.CounterByteArr[j] = this.CounterByteArr[i];

this.CounterByteArr[i] = temp;

let res_temp =

this.CounterByteArr[

(this.CounterByteArr[i] + this.CounterByteArr[j]) & 255

] ^ strBytes[k];

res[k] = res_temp <= 127 ? res_temp : res_temp - 256; // 转byte操作

}

return res;

}

unswapCounterXORPass(strBytes) {

let res = [];

let i = 0,

j = 0;

for (let k = 0; k < strBytes.length; k++) {

i = (i + 1) & 255;

j = (j + this.CounterByteArr[i]) & 255;

// 交换值

let temp = this.CounterByteArr[j];

this.CounterByteArr[j] = this.CounterByteArr[i];

this.CounterByteArr[i] = temp;

let res_temp =

strBytes[k] ^

this.CounterByteArr[

(this.CounterByteArr[i] + this.CounterByteArr[j]) & 255

];

res[k] = res_temp <= 127 ? res_temp : res_temp - 256; // 转byte操作

}

return res;

}

encodeMD5(bArr) {

let str = "";

for (const item of bArr) {

let temp = (item & 255).toString(16);

if (temp.length === 1) {

temp = "0" + temp;

}

str += temp.toLowerCase();

}

return str;

}

encodeChangePass(password) {

let md5s = md5.digest(password);

md5s.forEach((item, index) => {

if (item > 127) {

md5s[index] = item - 256;

}

});

return this.encodeMD5(md5s);

}

}

module.exports = {

MyEncrypt,

DateEnum,

};

声明:代码中除了 strToUtf8Bytes 函数和 md5 库外,其他函数均为自己实现,strToUtf8Bytes 函数为网上找到的,并做了一部分修改,用于将字符串转为 UTF-8 字节码来兼容汉字,不过看起来好像有点儿多余,因为密码不会是汉字,但是为了保险起见还是加上了。

如需转载请注明出处

使用

使用也是非常简单的

const { MyEncrypt, DateEnum, DateEnum2 } = require("./fyoung.js");

let daykey = DateEnum[new Date().getDate() - 1];

console.log(MyEncrypt.encryptPassword(daykey, "你的Fyoung密码"));

结语

可能 java 版本的代码大家都有,就不发了,没什么意思。这里只是分享一下 js 版本的,go 语言版本不太好放出来(因为那已经是一个完整的项目了,不管会不会都可以非常方便的打包出可执行文件),后续会单独抽出沃派WeNet的加密算法,至于认证我就不发了,还是得要留一些门槛的。

新版 Fyoung 已经来临,不论是何种校园网,有压迫就有斗争,绝不能屈服,我们需要一个良心的网络环境

后浪们,加油!

# fyoung # 逆向

编辑此页面

相关推荐