Files
douyin/utils/XBogus.cs
T
jianzhichu e6e9ff3cc3 1、去重
2、分享
3、视频播放
4、批量删除,重新下载
5、自定义标题(仅博主视频)
6、授权页面去掉博主添加,新增关注列表
7、图文视频合成优化
8、其他优化
2025-11-30 00:42:25 +08:00

291 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}");
// }
//}
}