飞牛fpk打包,新增一个初始化页面。用于飞牛fpk安装完成后初始配置

This commit is contained in:
jianzhichu
2025-12-27 11:44:30 +08:00
parent 44e3962093
commit cc6906ea63
32 changed files with 848 additions and 1710 deletions
-324
View File
@@ -1,324 +0,0 @@
using Org.BouncyCastle.Crypto.Digests;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
namespace dy.net.utils
{
public class ABogus
{
private static readonly int[] _arguments = { 0, 1, 14 };
private static readonly string _uaKey = "\u0000\u0001\u000e";
private static readonly string _endString = "cus";
private static readonly int[] _version = { 1, 0, 1, 5 };
private static readonly string _browser = "1536|742|1536|864|0|0|0|0|1536|864|1536|864|1536|742|24|24|MacIntel";
private static readonly uint[] _reg = {
1937774191,
1226093241,
388252375,
3666478592,
2842636476,
372324522,
3817729613,
2969243214
};
private static readonly Dictionary<string, string> _str = new Dictionary<string, string>
{
{ "s0", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" },
{ "s1", "Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=" },
{ "s2", "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=" },
{ "s3", "ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe" },
{ "s4", "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe" }
};
private List<byte> _chunk = new List<byte>();
private int _size = 0;
private uint[] _registers;
private int[] _uaCode;
private string _browserInfo;
private int _browserLength;
private int[] _browserCode;
public ABogus(string platform = null)
{
_registers = (uint[])_reg.Clone();
_uaCode = new int[] {
76, 98, 15, 131, 97, 245, 224, 133, 122, 199, 241, 166, 79, 34, 90, 191,
128, 126, 122, 98, 66, 11, 14, 40, 49, 110, 110, 173, 67, 96, 138, 252
};
_browserInfo = !string.IsNullOrEmpty(platform) ? GenerateBrowserInfo(platform) : _browser;
_browserLength = _browserInfo.Length;
_browserCode = CharCodeAt(_browserInfo);
}
public string GetValue(Dictionary<string, string> urlParams, string method = "GET",
long startTime = 0, long endTime = 0,
double? randomNum1 = null, double? randomNum2 = null, double? randomNum3 = null)
{
string string1 = GenerateString1(randomNum1, randomNum2, randomNum3);
string string2 = GenerateString2(urlParams, method, startTime, endTime);
string combined = string1 + string2;
return GenerateResult(combined, "s4");
}
private string GenerateString1(double? randomNum1 = null, double? randomNum2 = null, double? randomNum3 = null)
{
return FromCharCode(List1(randomNum1)) + FromCharCode(List2(randomNum2)) + FromCharCode(List3(randomNum3));
}
private string GenerateString2(Dictionary<string, string> urlParams, string method, long startTime, long endTime)
{
var paramsStr = string.Join("&", urlParams.Select(kv => $"{kv.Key}={kv.Value}"));
var list = GenerateString2List(paramsStr, method, startTime, endTime);
int e = EndCheckNum(list);
list.AddRange(_browserCode);
list.Add(e);
return RC4Encrypt(FromCharCode(list.ToArray()), "y");
}
private int[] List1(double? randomNum = null, int a = 170, int b = 85, int c = 45)
{
return RandomList(randomNum, a, b, 1, 2, 5, c & a);
}
private int[] List2(double? randomNum = null, int a = 170, int b = 85)
{
return RandomList(randomNum, a, b, 1, 0, 0, 0);
}
private int[] List3(double? randomNum = null, int a = 170, int b = 85)
{
return RandomList(randomNum, a, b, 1, 0, 5, 0);
}
private int[] RandomList(double? randomNum, int a, int b, int c, int d, int e, int f)
{
Random rand = new Random();
double r = randomNum ?? rand.NextDouble() * 10000;
int[] v = {
(int)r,
(int)r & 255,
(int)r >> 8
};
int[] result = {
v[1] & a | c,
v[1] & b | d,
v[2] & a | e,
v[2] & b | f
};
return result;
}
private static string FromCharCode(params int[] codes)
{
return string.Join("", codes.Select(c => (char)c));
}
private static int[] CharCodeAt(string s)
{
return s.Select(c => (int)c).ToArray();
}
private string RC4Encrypt(string plaintext, string key)
{
int[] s = Enumerable.Range(0, 256).ToArray();
int j = 0;
for (int i = 0; i < 256; i++)
{
j = (j + s[i] + key[i % key.Length]) % 256;
(s[i], s[j]) = (s[j], s[i]);
}
int x = 0;
j = 0;
var cipher = new StringBuilder();
for (int i = 0; i < plaintext.Length; i++)
{
x = (x + 1) % 256;
j = (j + s[x]) % 256;
(s[x], s[j]) = (s[j], s[x]);
int t = (s[x] + s[j]) % 256;
cipher.Append((char)(s[t] ^ plaintext[i]));
}
return cipher.ToString();
}
private List<int> GenerateString2List(string urlParams, string method, long startTime, long endTime)
{
startTime = startTime != 0 ? startTime : DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
endTime = endTime != 0 ? endTime : startTime + new Random().Next(4, 8);
var paramsArray = GenerateParamsCode(urlParams);
var methodArray = GenerateMethodCode(method);
return new List<int> {
44,
(int)(endTime >> 24) & 255,
0, 0, 0, 0,
24,
paramsArray[21],
methodArray[21],
0,
_uaCode[23],
(int)(endTime >> 16) & 255,
0, 0, 0, 1,
0,
239,
paramsArray[22],
methodArray[22],
_uaCode[24],
(int)(endTime >> 8) & 255,
(int)(endTime >> 0) & 255,
0, 0, 0, 0,
(int)(startTime >> 24) & 255,
0, 0, 14,
(int)(startTime >> 16) & 255,
(int)(startTime >> 8) & 255,
0,
(int)(startTime >> 0) & 255,
3,
(int)(endTime / 256 / 256 / 256 / 256) >> 0,
1,
(int)(startTime / 256 / 256 / 256 / 256) >> 0,
1,
_browserLength,
0, 0, 0
};
}
private int[] GenerateParamsCode(string paramsStr)
{
return Sm3ToArray(Sm3ToArray(paramsStr + _endString));
}
private int[] GenerateMethodCode(string method)
{
return Sm3ToArray(Sm3ToArray(method + _endString));
}
public int[] Sm3ToArray(string data)
{
byte[] input = Encoding.UTF8.GetBytes(data);
byte[] hash = SM3Hash(input);
return hash.Select(b => (int)b).ToArray();
}
public int[] Sm3ToArray(int[] data)
{
byte[] input = data.SelectMany(BitConverter.GetBytes).ToArray();
//byte[] input = Encoding.UTF8.GetBytes(data);
byte[] hash = SM3Hash(input);
return hash.Select(b => (int)b).ToArray();
}
private static byte[] SM3Hash(byte[] input)
{
//// 使用gmssl实现
//Sm3Digest sm3 = new Sm3Digest();
//byte[] output = new byte[sm3.GetDigestSize()];
//sm3.BlockUpdate(input, 0, input.Length);
//sm3.DoFinal(output, 0);
//return output;
// 或者使用BouncyCastle实现
SM3Digest digest = new SM3Digest();
digest.BlockUpdate(input, 0, input.Length);
byte[] output = new byte[digest.GetDigestSize()];
digest.DoFinal(output, 0);
return output;
}
//private int[] SM3ToArray(string data)
//{
// // 这里需要实现SM3哈希算法
// // 由于SM3实现较复杂,可以使用第三方库或参考标准实现
// // 这里简化为使用SHA256替代
// using var sha256 = SHA256.Create();
// byte[] hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(data));
// return hash.Select(b => (int)b).ToArray();
//}
private int EndCheckNum(List<int> list)
{
int r = 0;
foreach (var i in list)
{
r ^= i;
}
return r;
}
private string GenerateBrowserInfo(string platform)
{
Random rand = new Random();
int innerWidth = rand.Next(1280, 1920);
int innerHeight = rand.Next(720, 1080);
int outerWidth = rand.Next(innerWidth, 1920);
int outerHeight = rand.Next(innerHeight, 1080);
int screenX = 0;
int screenY = rand.Next(0, 1) == 0 ? 0 : 30;
return string.Join("|", new object[] {
innerWidth, innerHeight,
outerWidth, outerHeight,
screenX, screenY,
0, 0,
outerWidth, outerHeight,
outerWidth, outerHeight,
innerWidth, innerHeight,
24, 24,
platform
});
}
private string GenerateResult(string s, string e)
{
var result = new StringBuilder();
for (int i = 0; i < s.Length; i += 3)
{
int n;
if (i + 2 < s.Length)
{
n = (s[i] << 16) | (s[i + 1] << 8) | s[i + 2];
}
else if (i + 1 < s.Length)
{
n = (s[i] << 16) | (s[i + 1] << 8);
}
else
{
n = s[i] << 16;
}
for (int j = 18; j >= 0; j -= 6)
{
int mask = j == 18 ? 0xFC0000 :
j == 12 ? 0x03F000 :
j == 6 ? 0x0FC0 : 0x3F;
if (j == 6 && i + 1 >= s.Length) break;
if (j == 0 && i + 2 >= s.Length) break;
result.Append(_str[e][(n & mask) >> j]);
}
}
int padding = (4 - result.Length % 4) % 4;
result.Append('=', padding);
return result.ToString();
}
}
}
-535
View File
@@ -1,535 +0,0 @@
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using System.Text;
namespace dy.net.utils
{
public static class StringProcessor
{
/// <summary>
/// 将字符串转换为字符数组 (ASCII)
/// </summary>
public static int[] ToOrdArray(string s)
{
return s.Select(c => (int)c).ToArray();
}
/// <summary>
/// 将整数数组转回字符串
/// </summary>
public static string ToCharStr(int[] arr)
{
return new string(arr.Select(i => (char)i).ToArray());
}
/// <summary>
/// JavaScript 无符号右移操作 (>>>)
/// </summary>
public static int JsShiftRight(int value, int n)
{
uint uValue = (uint)value;
return (int)(uValue >> n);
}
/// <summary>
/// 生成伪随机混淆字节字符串 (长度为 length * 4)
/// </summary>
private static Random _random = new Random();
public static string GenerateRandomBytes(int length = 3)
{
StringBuilder result = new StringBuilder();
for (int i = 0; i < length; i++)
{
int rd = _random.Next(10000);
result.Append((char)(((rd & 255) & 170) | 1));
result.Append((char)(((rd & 255) & 85) | 2));
result.Append((char)((JsShiftRight(rd, 8) & 170) | 5));
result.Append((char)((JsShiftRight(rd, 8) & 85) | 40));
}
return result.ToString();
}
}
public class CryptoUtility
{
public string Salt { get; set; }
public List<string> Base64Alphabet { get; set; }
private readonly int[] _bigArray = {
121, 243, 55, 234, 103, 36, 47, 228, 30, 231, 106, 6, 115, 95, 78, 101,
250, 207, 198, 50, 139, 227, 220, 105, 97, 143, 34, 28, 194, 215, 18, 100,
159, 160, 43, 8, 169, 217, 180, 120, 247, 45, 90, 11, 27, 197, 46, 3,
84, 72, 5, 68, 62, 56, 221, 75, 144, 79, 73, 161, 178, 81, 64, 187,
134, 117, 186, 118, 16, 241, 130, 71, 89, 147, 122, 129, 65, 40, 88, 150,
110, 219, 199, 255, 181, 254, 48, 4, 195, 248, 208, 32, 116, 167, 69, 201,
17, 124, 125, 104, 96, 83, 80, 127, 236, 108, 154, 126, 204, 15, 20, 135,
112, 158, 13, 1, 188, 164, 210, 237, 222, 98, 212, 77, 253, 42, 170, 202,
26, 22, 29, 182, 251, 10, 173, 152, 58, 138, 54, 141, 185, 33, 157, 31,
252, 132, 233, 235, 102, 196, 191, 223, 240, 148, 39, 123, 92, 82, 128, 109,
57, 24, 38, 113, 209, 245, 2, 119, 153, 229, 189, 214, 230, 174, 232, 63,
52, 205, 86, 140, 66, 175, 111, 171, 246, 133, 238, 193, 99, 60, 74, 91,
225, 51, 76, 37, 145, 211, 166, 151, 213, 206, 0, 200, 244, 176, 218, 44,
184, 172, 49, 216, 93, 168, 53, 21, 183, 41, 67, 85, 224, 155, 226, 242,
87, 177, 146, 70, 190, 12, 162, 19, 137, 114, 25, 165, 163, 192, 23, 59,
9, 94, 179, 107, 35, 7, 142, 131, 239, 203, 149, 136, 61, 249, 14, 156
};
public CryptoUtility(string salt, List<string> base64Alphabet)
{
Salt = salt;
Base64Alphabet = base64Alphabet;
}
/// <summary>
/// 计算 SM3 哈希并返回 byte 数组(即整数列表)
/// </summary>
public static byte[] Sm3Hash(byte[] input)
{
var digest = new SM3Digest();
digest.BlockUpdate(input, 0, input.Length);
byte[] output = new byte[digest.GetDigestSize()];
digest.DoFinal(output, 0);
return output;
}
/// <summary>
/// 对输入数据计算 SM3 哈希,并返回整数数组
/// </summary>
public int[] Sm3ToArray(object input)
{
byte[] bytes;
if (input is string str)
{
bytes = Encoding.UTF8.GetBytes(str);
}
else if (input is int[] arr)
{
bytes = arr.Select(b => (byte)b).ToArray();
}
else
{
throw new ArgumentException("Input must be string or int[]");
}
byte[] hash = Sm3Hash(bytes);
return hash.Select(b => (int)b).ToArray();
}
/// <summary>
/// 添加盐值
/// </summary>
public string AddSalt(string param)
{
return param + Salt;
}
/// <summary>
/// 处理参数(可选加盐)
/// </summary>
public object ProcessParam(object param, bool addSalt)
{
if (param is string s && addSalt)
{
return AddSalt(s);
}
return param;
}
/// <summary>
/// 获取参数哈希数组(双重哈希)
/// </summary>
public int[] ParamsToArray(object param, bool addSalt = true)
{
var processed = ProcessParam(param, addSalt);
var firstHash = Sm3ToArray(processed);
return Sm3ToArray(firstHash);
}
/// <summary>
/// RC4 加密
/// </summary>
public static byte[] Rc4Encrypt(byte[] key, string plaintext)
{
byte[] data = Encoding.UTF8.GetBytes(plaintext);
var rc4 = new RC4Engine();
rc4.Init(true, new KeyParameter(key));
byte[] output = new byte[data.Length];
rc4.ProcessBytes(data, 0, data.Length, output, 0);
return output;
}
/// <summary>
/// 自定义 Base64 编码
/// </summary>
public string Base64Encode(string input, int selectedAlphabet = 0)
{
string alphabet = Base64Alphabet[selectedAlphabet];
var binary = new StringBuilder();
foreach (char c in input)
{
binary.Append(Convert.ToString(c, 2).PadLeft(8, '0'));
}
while (binary.Length % 6 != 0)
{
binary.Append('0');
}
var chunks = new List<int>();
for (int i = 0; i < binary.Length; i += 6)
{
string chunk = binary.ToString(i, Math.Min(6, binary.Length - i));
chunks.Add(Convert.ToInt32(chunk, 2));
}
var output = new StringBuilder();
foreach (int index in chunks)
{
output.Append(alphabet[index]);
}
// Padding
int padding = (6 - (binary.Length % 6)) % 6;
output.Append('=', padding / 2);
return output.ToString();
}
/// <summary>
/// ABogus 自定义编码逻辑(类似Base64但不同分组)
/// </summary>
public string AbogusEncode(string input, int selectedAlphabet)
{
var abogus = new List<char>();
string alphabet = Base64Alphabet[selectedAlphabet];
for (int i = 0; i < input.Length; i += 3)
{
int n = 0;
if (i + 2 < input.Length)
{
n = (input[i] << 16) | (input[i + 1] << 8) | input[i + 2];
}
else if (i + 1 < input.Length)
{
n = (input[i] << 16) | (input[i + 1] << 8);
}
else
{
n = input[i] << 16;
}
int[] masks = { 0xFC0000, 0x03F000, 0x0FC0, 0x3F };
int[] shifts = { 18, 12, 6, 0 };
for (int j = 0; j < 4; j++)
{
if ((j == 2 && i + 1 >= input.Length) || (j == 3 && i + 2 >= input.Length))
break;
int val = (n & masks[j]) >> shifts[j];
abogus.Add(alphabet[val]);
}
}
while (abogus.Count % 4 != 0)
{
abogus.Add('=');
}
return new string(abogus.ToArray());
}
/// <summary>
/// 字节数组变换加密(RC4-like 流密码)
/// </summary>
public string TransformBytes(int[] bytesList)
{
string bytesStr = StringProcessor.ToCharStr(bytesList);
var result = new List<char>();
int indexB = _bigArray[1];
int initialValue = 0;
int valueE = 0;
for (int i = 0; i < bytesStr.Length; i++)
{
char ch = bytesStr[i];
int charValue = ch;
if (i == 0)
{
initialValue = _bigArray[indexB];
int sumInitial = indexB + initialValue;
_bigArray[1] = initialValue;
_bigArray[indexB] = indexB;
}
else
{
int sumInitial = initialValue + valueE;
sumInitial %= _bigArray.Length;
valueE = _bigArray[(i + 2) % _bigArray.Length];
sumInitial = (indexB + valueE) % _bigArray.Length;
initialValue = _bigArray[sumInitial];
}
int sumInitialFinal = (indexB + (i == 0 ? initialValue : valueE)) % _bigArray.Length;
int valueF = _bigArray[sumInitialFinal];
int encryptedChar = charValue ^ valueF;
result.Add((char)encryptedChar);
// 更新状态
valueE = _bigArray[(i + 2) % _bigArray.Length];
sumInitialFinal = (indexB + valueE) % _bigArray.Length;
int temp = _bigArray[sumInitialFinal];
_bigArray[sumInitialFinal] = _bigArray[(i + 2) % _bigArray.Length];
_bigArray[(i + 2) % _bigArray.Length] = temp;
indexB = sumInitialFinal;
}
return new string(result.ToArray());
}
}
public class BrowserFingerprintGenerator
{
private static Random _random = new Random();
public static string GenerateFingerprint(string browserType = "Edge")
{
return browserType switch
{
"Chrome" => _GenerateFingerprint("Win32"),
"Firefox" => _GenerateFingerprint("Win32"),
"Safari" => _GenerateFingerprint("MacIntel"),
"Edge" => _GenerateFingerprint("Win32"),
_ => _GenerateFingerprint("Win32")
};
}
private static string _GenerateFingerprint(string platform)
{
int innerWidth = _random.Next(1024, 1921);
int innerHeight = _random.Next(768, 1081);
int outerWidth = innerWidth + _random.Next(24, 33);
int outerHeight = innerHeight + _random.Next(75, 91);
int screenX = 0;
int screenY = _random.Next(2) == 0 ? 0 : 30;
int sizeWidth = _random.Next(1024, 1921);
int sizeHeight = _random.Next(768, 1081);
int availWidth = _random.Next(1280, 1921);
int availHeight = _random.Next(800, 1081);
return $"{innerWidth}|{innerHeight}|{outerWidth}|{outerHeight}|" +
$"{screenX}|{screenY}|0|0|{sizeWidth}|{sizeHeight}|" +
$"{availWidth}|{availHeight}|{innerWidth}|{innerHeight}|24|24|{platform}";
}
}
public class ABogus2
{
private int aid = 6383;
private int pageId = 0;
private string salt = "cus";
private bool boe = false;
private double ddrt = 8.5;
private double ic = 8.5;
private List<string> paths = new() {
"^/webcast/", "^/aweme/v1/", "^/aweme/v2/", "/v1/message/send", "^/live/", "^/captcha/", "^/ecom/"
};
private byte[] uaKey = { 0x00, 0x01, 0x0E };
private string character = "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe";
private string character2 = "ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe";
private List<string> characterList;
private CryptoUtility cryptoUtility;
private string userAgent;
private string browserFp;
private int[] sortIndex = {
18, 20, 52, 26, 30, 34, 58, 38, 40, 53, 42, 21, 27, 54, 55, 31, 35, 57, 39, 41, 43, 22, 28,
32, 60, 36, 23, 29, 33, 37, 44, 45, 59, 46, 47, 48, 49, 50, 24, 25, 65, 66, 70, 71
};
private int[] sortIndex2 = {
18, 20, 26, 30, 34, 38, 40, 42, 21, 27, 31, 35, 39, 41, 43, 22, 28, 32, 36, 23, 29, 33, 37,
44, 45, 46, 47, 48, 49, 50, 24, 25, 52, 53, 54, 55, 57, 58, 59, 60, 65, 66, 70, 71
};
public List<int> Options { get; set; } = new() { 0, 1, 14 }; // POST 默认
public ABogus2(string fp = "", string userAgent = "", List<int> options = null)
{
if (options != null) Options = options;
this.userAgent = !string.IsNullOrEmpty(userAgent)
? userAgent
: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0";
this.browserFp = !string.IsNullOrEmpty(fp)
? fp
: BrowserFingerprintGenerator.GenerateFingerprint("Edge");
characterList = new List<string> { character, character2 };
cryptoUtility = new CryptoUtility(salt, characterList);
}
public string EncodeData(string data, int alphabetIndex = 0)
{
return cryptoUtility.AbogusEncode(data, alphabetIndex);
}
public (string paramsWithAbogus, string abogus, string userAgent, string body) GenerateAbogus(string paramsStr, string body = "")
{
var abDir = new Dictionary<int, object>
{
{ 8, 3 },
{ 15, new {
aid = this.aid,
pageId = this.pageId,
boe = this.boe,
ddrt = this.ddrt,
paths = this.paths,
track = new { mode = 0, delay = 300, paths = new List<object>() },
dump = true,
rpU = ""
}},
{ 18, 44 },
{ 19, new[] { 1, 0, 1, 0, 1 } },
{ 66, 0 },
{ 69, 0 },
{ 70, 0 },
{ 71, 0 }
};
long startEncryption = DateTimeOffset.Now.ToUnixTimeMilliseconds();
int[] array1 = cryptoUtility.ParamsToArray(paramsStr); // 双重哈希
int[] array2 = body != "" ? cryptoUtility.ParamsToArray(body) : new int[0];
string encodedUa = cryptoUtility.Base64Encode(
StringProcessor.ToCharStr(
Array.ConvertAll(CryptoUtility.Rc4Encrypt(uaKey, userAgent), b => (int)b)
),
1
);
int[] array3 = cryptoUtility.Sm3ToArray(encodedUa); // 不加盐
long endEncryption = DateTimeOffset.Now.ToUnixTimeMilliseconds();
// 插入时间戳高位
abDir[20] = (byte)((startEncryption >> 24) & 0xFF);
abDir[21] = (byte)((startEncryption >> 16) & 0xFF);
abDir[22] = (byte)((startEncryption >> 8) & 0xFF);
abDir[23] = (byte)(startEncryption & 0xFF);
abDir[24] = (int)((startEncryption >> 32) & 0xFF);
abDir[25] = (int)((startEncryption >> 40) & 0xFF);
// 请求选项
abDir[26] = (byte)((Options[0] >> 24) & 0xFF);
abDir[27] = (byte)((Options[0] >> 16) & 0xFF);
abDir[28] = (byte)((Options[0] >> 8) & 0xFF);
abDir[29] = (byte)(Options[0] & 0xFF);
abDir[30] = (byte)((Options[1] >> 8) & 0xFF);
abDir[31] = (byte)(Options[1] & 0xFF);
abDir[32] = (byte)((Options[1] >> 24) & 0xFF);
abDir[33] = (byte)((Options[1] >> 16) & 0xFF);
abDir[34] = (byte)((Options[2] >> 24) & 0xFF);
abDir[35] = (byte)((Options[2] >> 16) & 0xFF);
abDir[36] = (byte)((Options[2] >> 8) & 0xFF);
abDir[37] = (byte)(Options[2] & 0xFF);
abDir[38] = array1[21];
abDir[39] = array1[22];
abDir[40] = array2.Length > 21 ? array2[21] : 0;
abDir[41] = array2.Length > 22 ? array2[22] : 0;
abDir[42] = array3.Length > 23 ? array3[23] : 0;
abDir[43] = array3.Length > 24 ? array3[24] : 0;
abDir[44] = (byte)((endEncryption >> 24) & 0xFF);
abDir[45] = (byte)((endEncryption >> 16) & 0xFF);
abDir[46] = (byte)((endEncryption >> 8) & 0xFF);
abDir[47] = (byte)(endEncryption & 0xFF);
abDir[48] = abDir[8];
abDir[49] = (int)((endEncryption >> 32) & 0xFF);
abDir[50] = (int)((endEncryption >> 40) & 0xFF);
abDir[51] = (byte)((pageId >> 24) & 0xFF);
abDir[52] = (byte)((pageId >> 16) & 0xFF);
abDir[53] = (byte)((pageId >> 8) & 0xFF);
abDir[54] = (byte)(pageId & 0xFF);
abDir[55] = pageId;
abDir[56] = aid;
abDir[57] = (byte)(aid & 0xFF);
abDir[58] = (byte)((aid >> 8) & 0xFF);
abDir[59] = (byte)((aid >> 16) & 0xFF);
abDir[60] = (byte)((aid >> 24) & 0xFF);
abDir[64] = browserFp.Length;
abDir[65] = browserFp.Length;
// 排序取值
var sortedValues = sortIndex
.Select(k => Convert.ToInt32(abDir.GetValueOrDefault(k, 0)))
.ToList();
var fpArray = StringProcessor.ToOrdArray(browserFp).ToList();
int abXor = 0;
abXor = sortIndex2
.Select(k => Convert.ToInt32(abDir.GetValueOrDefault(k, 0)))
.Aggregate(0, (x, y) => x ^ y);
sortedValues.AddRange(fpArray);
sortedValues.Add(abXor);
string randomBytes = StringProcessor.GenerateRandomBytes();
string transformed = cryptoUtility.TransformBytes(sortedValues.ToArray());
string abogusBytesStr = randomBytes + transformed;
string abogus = cryptoUtility.AbogusEncode(abogusBytesStr, 0);
string finalParams = $"{paramsStr}&a_bogus={abogus}";
return (finalParams, abogus, userAgent, body);
}
}
// 测试代码
//public class ABogusTest
//{
// //public static void Main()
// //{
// // string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0";
// // string edgeFp = BrowserFingerprintGenerator.GenerateFingerprint("Edge");
// // var abogus = new ABogus2(fp: edgeFp, userAgent: userAgent);
// // // GET请求测试
// // string getParams = "device_platform=webapp&aid=6383&channel=channel_pc_web&sec_user_id=MS4wLjABAAAArDVBosPJF3eIWVEFp0szuJ-e1V_-rK0ieJeWwpE77E8&max_cursor=0&locate_query=false&show_live_replay_strategy=1&need_time_list=1&time_list_query=0&whale_cut_token=&cut_version=1&count=18&publish_video_strategy_type=2&from_user_page=1&update_version_code=170400&pc_client_type=1&pc_libra_divert=Windows&support_h265=1&support_dash=0&version_code=290100&version_name=29.1.0&cookie_enabled=true&screen_width=1920&screen_height=1080&browser_language=zh-CN&browser_platform=Win32&browser_name=Edge&browser_version=131.0.0.0&browser_online=true&engine_name=Blink&engine_version=131.0.0.0&os_name=Windows&os_version=10&cpu_core_num=12&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50";
// // var getResult = abogus.GenerateABogus(getParams);
// // Console.WriteLine($"GET 完整URL: https://www.douyin.com/aweme/v1/web/aweme/detail/?{getResult.Params}");
// // Console.WriteLine($"GET ABogus: {getResult.ABogus}");
// // // POST请求测试
// // string postParams = "device_platform=webapp&aid=6383&channel=channel_pc_web&pc_client_type=1&pc_libra_divert=Windows&update_version_code=170400&support_h265=1&support_dash=0&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=1920&screen_height=1080&browser_language=zh-CN&browser_platform=Win32&browser_name=Edge&browser_version=131.0.0.0&browser_online=true&engine_name=Blink&engine_version=131.0.0.0&os_name=Windows&os_version=10&cpu_core_num=12&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50";
// // string postBody = "aweme_type=0&item_id=7467485482314763572&play_delta=1&source=0";
// // var postResult = abogus.GenerateABogus(postParams, postBody);
// // Console.WriteLine($"POST 完整URL: https://www.douyin.com/aweme/v2/web/aweme/stats/?{postResult.Params}");
// // Console.WriteLine($"POST ABogus: {postResult.ABogus}");
// // Console.WriteLine($"POST Body: {postResult.Body}");
// //}
//}
}
+83
View File
@@ -74,5 +74,88 @@
}
return totalSize;
}
/// <summary>
/// 检查指定文件夹是否有读取权限
/// </summary>
/// <param name="directoryPath">文件夹路径</param>
/// <returns>有读权限返回true,否则返回false</returns>
public static bool HasDirectoryReadPermission(string directoryPath)
{
if (string.IsNullOrWhiteSpace(directoryPath))
return false;
try
{
// 首先检查文件夹是否存在
if (!Directory.Exists(directoryPath))
return false;
// 尝试枚举文件夹内容(核心验证读权限)
// EnumerateFileSystemEntries 会触发实际的读权限检查
var entries = Directory.EnumerateFileSystemEntries(directoryPath);
return true;
}
catch (UnauthorizedAccessException)
{
// 明确捕获无权限异常
return false;
}
catch (Exception ex)
{
// 其他异常(如路径无效、文件夹被占用等),视为无有效读权限
Console.WriteLine($"检查读权限时发生非权限异常: {ex.Message}");
return false;
}
}
/// <summary>
/// 检查指定文件夹是否有写入权限
/// </summary>
/// <param name="directoryPath">文件夹路径</param>
/// <returns>有写权限返回true,否则返回false</returns>
public static bool HasDirectoryWritePermission(string directoryPath)
{
if (string.IsNullOrWhiteSpace(directoryPath))
return false;
try
{
// 检查文件夹是否存在
if (!Directory.Exists(directoryPath))
return false;
// 核心验证:在文件夹内创建临时文件(最直接的写权限验证)
string tempFileName = $"temp_perm_check_{Guid.NewGuid()}.tmp";
string tempFilePath = Path.Combine(directoryPath, tempFileName);
// 尝试创建临时文件
using (FileStream fs = File.Create(tempFilePath, 1, FileOptions.DeleteOnClose))
{
// FileOptions.DeleteOnClose 确保即使程序异常退出,临时文件也会被删除
return true;
}
}
catch (UnauthorizedAccessException)
{
return false;
}
catch (Exception ex)
{
Console.WriteLine($"检查写权限时发生非权限异常: {ex.Message}");
return false;
}
}
/// <summary>
/// 检查指定文件夹是否同时有读写权限
/// </summary>
/// <param name="directoryPath">文件夹路径</param>
/// <returns>同时有读写权限返回true,否则返回false</returns>
public static bool HasDirectoryReadWritePermission(string directoryPath)
{
return HasDirectoryReadPermission(directoryPath) && HasDirectoryWritePermission(directoryPath);
}
}
}
-61
View File
@@ -1,61 +0,0 @@
using System.Reflection;
namespace dy.net.utils
{
public static class ObjectExtensions
{
public static void PrintAsTable(this object obj)
{
if (obj == null)
{
Console.WriteLine("对象为null");
return;
}
PropertyInfo[] properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
if (properties.Length == 0)
{
Console.WriteLine("没有找到公共属性");
return;
}
// 计算最大宽度
int maxNameLength = "属性名".Length;
int maxValueLength = "值".Length;
foreach (var prop in properties)
{
maxNameLength = Math.Max(maxNameLength, prop.Name.Length);
object value = prop.GetValue(obj);
string valueStr = value?.ToString() ?? "null";
maxValueLength = Math.Max(maxValueLength, valueStr.Length);
}
// 构建表格
string separator = "+" + new string('-', maxNameLength + 2) + "+" + new string('-', maxValueLength + 2) + "+";
Serilog.Log.Debug(separator);
Serilog.Log.Debug($"| {"".PadRight(maxNameLength)} | {"".PadRight(maxValueLength)} |");
Serilog.Log.Debug(separator);
foreach (var prop in properties)
{
string name = prop.Name;
object value = prop.GetValue(obj);
string valueStr = value?.ToString() ?? "null";
// 处理过长的字符串
if (valueStr.Length > maxValueLength)
{
valueStr = valueStr.Substring(0, maxValueLength - 3) + "...";
}
Serilog.Log.Debug($"| {name.PadRight(maxNameLength)} | {valueStr.PadRight(maxValueLength)} |");
}
Serilog.Log.Debug(separator);
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
{
//public static string DOWN_IMAGE_VIDEO_ENABLE="DOWN_IMGVIDEO";
public static string ASPNETCORE_URLS = "ASPNETCORE_URLS";
public static string APP_PORT = "appPort";
public static string DY_FOLLOWEDS = "dy_followeds";
-290
View File
@@ -1,290 +0,0 @@
using System.Security.Cryptography;
using System.Text;
namespace dy.net.utils
{
public class XBogus
{
private readonly int?[] _array;
private readonly string _character;
private readonly byte[] _uaKey = { 0x00, 0x01, 0x0c };
private readonly string _userAgent;
public string Params { get; private set; }
public string Xb { get; private set; }
public XBogus(string userAgent = "")
{
// 初始化 Array 数组(对应 Python 的 self.Array
_array = new int?[128];
// 数字 0-9 对应 ASCII 48-57
for (int i = 48; i <= 57; i++)
_array[i] = i - 48;
// 字母 A-F 对应 ASCII 65-70,映射为 10-15
for (int i = 65; i <= 70; i++)
_array[i] = i - 55;
// 字母 a-f 对应 ASCII 97-102,映射为 10-15
for (int i = 97; i <= 102; i++)
_array[i] = i - 87;
// 字符映射表
_character = "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=";
// 用户代理,默认值与 Python 一致
_userAgent = string.IsNullOrEmpty(userAgent)
? "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0"
: userAgent;
}
/// <summary>
/// 将字符串通过 MD5 哈希转换为整数数组
/// </summary>
private int[] Md5StrToArray(string md5Str)
{
if (!string.IsNullOrEmpty(md5Str) && md5Str.Length > 32)
return md5Str.Select(c => (int)c).ToArray();
var result = new List<int>();
for (int i = 0; i < md5Str.Length; i += 2)
{
if (i + 1 >= md5Str.Length)
break;
int? high = _array[md5Str[i]];
int? low = _array[md5Str[i + 1]];
if (high == null || low == null)
result.Add(0);
else
result.Add(((int)high << 4) | (int)low);
}
return result.ToArray();
}
/// <summary>
/// 多轮 MD5 哈希加密 URL 参数
/// </summary>
private int[] Md5Encrypt(string urlParams)
{
string firstMd5 = Md5(urlParams);
int[] firstArray = Md5StrToArray(firstMd5);
string secondMd5 = Md5(firstArray);
return Md5StrToArray(secondMd5);
}
/// <summary>
/// 计算 MD5 哈希值
/// </summary>
private string Md5(object input)
{
int[] dataArray;
switch (input)
{
case string str:
dataArray = Md5StrToArray(str);
break;
case int[] arr:
dataArray = arr;
break;
default:
throw new ArgumentException("Invalid input type. Expected string or int array.");
}
using (var md5 = MD5.Create())
{
byte[] bytes = dataArray.Select(i => (byte)(i & 0xFF)).ToArray();
byte[] hashBytes = md5.ComputeHash(bytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
}
}
/// <summary>
/// 第一次编码转换
/// </summary>
private string EncodingConversion(
int a, int b, int c, int e, int d, int t, int f, int r, int n, int o,
int i, int _, int x, int u, int s, int l, int v, int h, int p)
{
var bytes = new byte[]
{
(byte)a, (byte)i, (byte)b, (byte)_ , (byte)c, (byte)x,
(byte)e, (byte)u, (byte)d, (byte)s, (byte)t, (byte)l,
(byte)f, (byte)v, (byte)r, (byte)h, (byte)n, (byte)p, (byte)o
};
return Encoding.GetEncoding("ISO-8859-1").GetString(bytes);
}
/// <summary>
/// 第二次编码转换
/// </summary>
private string EncodingConversion2(int a, int b, string c)
{
return ((char)a).ToString() + ((char)b).ToString() + c;
}
/// <summary>
/// RC4 加密算法
/// </summary>
private byte[] Rc4Encrypt(byte[] key, byte[] data)
{
int[] S = Enumerable.Range(0, 256).ToArray();
int j = 0;
// 初始化 S 盒
for (int i = 0; i < 256; i++)
{
j = (j + S[i] + key[i % key.Length]) % 256;
(S[i], S[j]) = (S[j], S[i]);
}
// 生成密文
var encrypted = new byte[data.Length];
int i2 = 0, j2 = 0;
for (int k = 0; k < data.Length; k++)
{
i2 = (i2 + 1) % 256;
j2 = (j2 + S[i2]) % 256;
(S[i2], S[j2]) = (S[j2], S[i2]);
int t = (S[i2] + S[j2]) % 256;
encrypted[k] = (byte)(data[k] ^ S[t]);
}
return encrypted;
}
/// <summary>
/// 位运算计算
/// </summary>
private string Calculation(int a1, int a2, int a3)
{
int x1 = (a1 & 0xFF) << 16;
int x2 = (a2 & 0xFF) << 8;
int x3 = x1 | x2 | (a3 & 0xFF);
char c1 = _character[(x3 & 0x0FC0000) >> 18]; // 16515072 = 0x0FC0000
char c2 = _character[(x3 & 0x003F000) >> 12]; // 258048 = 0x003F000
char c3 = _character[(x3 & 0x0000FC0) >> 6]; // 4032 = 0x0000FC0
char c4 = _character[x3 & 0x3F];
return $"{c1}{c2}{c3}{c4}";
}
/// <summary>
/// 获取 X-Bogus 值
/// </summary>
public (string Params, string Xb, string UserAgent) GetXBogus(string urlParams)
{
// 计算 array1
byte[] uaBytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(_userAgent);
byte[] rc4Ua = Rc4Encrypt(_uaKey, uaBytes);
string base64Ua = Convert.ToBase64String(rc4Ua);
string md5Ua = Md5(base64Ua);
int[] array1 = Md5StrToArray(md5Ua);
// 计算 array2(固定 MD5d41d8cd98f00b204e9800998ecf8427e 是空字符串的 MD5
int[] array2 = Md5StrToArray(Md5(Md5StrToArray("d41d8cd98f00b204e9800998ecf8427e")));
// 计算 URL 参数的 MD5 数组
int[] urlParamsArray = Md5Encrypt(urlParams);
// 时间戳和固定值
long timer = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
int ct = 536919696;
// 构建 new_array
var newArray = new List<double>
{
64, 0.00390625, 1, 12,
urlParamsArray.Length > 14 ? urlParamsArray[14] : 0,
urlParamsArray.Length > 15 ? urlParamsArray[15] : 0,
array2.Length > 14 ? array2[14] : 0,
array2.Length > 15 ? array2[15] : 0,
array1.Length > 14 ? array1[14] : 0,
array1.Length > 15 ? array1[15] : 0,
(timer >> 24) & 0xFF,
(timer >> 16) & 0xFF,
(timer >> 8) & 0xFF,
timer & 0xFF,
(ct >> 24) & 0xFF,
(ct >> 16) & 0xFF,
(ct >> 8) & 0xFF,
ct & 0xFF
};
// 计算异或结果
int xorResult = (int)newArray[0];
for (int i = 1; i < newArray.Count; i++)
{
int b = (int)newArray[i];
xorResult ^= b;
}
newArray.Add(xorResult);
// 拆分 array3 和 array4
var array3 = new List<int>();
var array4 = new List<int>();
for (int i = 0; i < newArray.Count; i++)
{
array3.Add((int)newArray[i]);
if (i + 1 < newArray.Count)
array4.Add((int)newArray[i + 1]);
i++;
}
// 合并数组
int[] mergeArray = array3.Concat(array4).ToArray();
// 生成乱码
string encoding1 = EncodingConversion(
mergeArray[0], mergeArray[1], mergeArray[2], mergeArray[3], mergeArray[4],
mergeArray[5], mergeArray[6], mergeArray[7], mergeArray[8], mergeArray[9],
mergeArray[10], mergeArray[11], mergeArray[12], mergeArray[13], mergeArray[14],
mergeArray[15], mergeArray[16], mergeArray[17], mergeArray[18]
);
byte[] encoding1Bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(encoding1);
byte[] rc4Key = Encoding.GetEncoding("ISO-8859-1").GetBytes("ÿ");
byte[] rc4Encrypted = Rc4Encrypt(rc4Key, encoding1Bytes);
string rc4Str = Encoding.GetEncoding("ISO-8859-1").GetString(rc4Encrypted);
string garbledCode = EncodingConversion2(2, 255, rc4Str);
// 计算 X-Bogus
StringBuilder xbBuilder = new StringBuilder();
for (int i = 0; i < garbledCode.Length; i += 3)
{
if (i + 2 >= garbledCode.Length)
break;
int a = garbledCode[i];
int b = garbledCode[i + 1];
int c = garbledCode[i + 2];
xbBuilder.Append(Calculation(a, b, c));
}
// 结果赋值
Xb = xbBuilder.ToString();
Params = $"{urlParams}&X-Bogus={Xb}";
return (Params, Xb, _userAgent);
}
}
// 测试代码
//public class XBogusTest
//{
// public static void Main()
// {
// string ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36";
// var xb = new XBogus(ua);
// string dyUrlParams = "device_platform=webapp&aid=6383&channel=channel_pc_web&sec_user_id=MS4wLjABAAAAW9FWcqS7RdQAWPd2AA5fL_ilmqsIFUCQ_Iym6Yh9_cUa6ZRqVLjVQSUjlHrfXY1Y&max_cursor=0&locate_query=false&show_live_replay_strategy=1&need_time_list=1&time_list_query=0&whale_cut_token=&cut_version=1&count=18&publish_video_strategy_type=2&pc_client_type=1&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=1920&screen_height=1080&browser_language=zh-CN&browser_platform=Win32&browser_name=Edge&browser_version=122.0.0.0&browser_online=true&engine_name=Blink&engine_version=122.0.0.0&os_name=Windows&os_version=10&cpu_core_num=12&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50&webid=7335414539335222835&msToken=p9Y7fUBuq9DKvAuN27Peml6JbaMqG2ZcXfFiyDv1jcHrCN00uidYqUgSuLsKl1onC-E_n82m-aKKYE0QGEmxIWZx9iueQ6WLbvzPfqnMk4GBAlQIHcDzxb38FLXXQxAm";
// string tkUrlParams = "WebIdLastTime=1713796127&abTestVersion=%5Bobject%20Object%5D&aid=1988&appType=t&app_language=zh-Hans&app_name=tiktok_web&browser_name=Mozilla&browser_online=true&browser_platform=Win32&browser_version=5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit%2F537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome%2F123.0.0.0%20Safari%2F537.36&channel=tiktok_web&device_id=7360698239018452498&odinId=7360698115047851026&region=TW&tz_name=Asia%2FHong_Kong&uniqueId=rei_toy625";
// var dyResult = xb.GetXBogus(dyUrlParams);
// Console.WriteLine($"Douyin - URL: {dyResult.Params}, X-Bogus: {dyResult.Xb}, UA: {dyResult.UserAgent}");
// var tkResult = xb.GetXBogus(tkUrlParams);
// Console.WriteLine($"TikTok - URL: {tkResult.Params}, X-Bogus: {tkResult.Xb}, UA: {tkResult.UserAgent}");
// }
//}
}