207 lines
6.2 KiB
C#
Raw Permalink Normal View History

2024-11-25 15:33:52 +08:00
using System.Globalization;
using System.Text;
class Program
{
static void Main()
{
//Check("chenx221", "12345678"); // debug
Console.Write("Enter name: ");
string? name = Console.ReadLine();
if (name == null)
throw new ArgumentNullException(nameof(name), "Name cannot be null.");
CalcSerial(name);
Console.ReadKey();
}
public static void CalcSerial(string user)
{
if (!CheckStrLen(user, 5, 0))
throw new ArgumentException("Invalid user string length.");
uint eax, ecx;
ushort cx;
byte cl, ch, dl = 0;
byte[] userBytes;
foreach (char c in user[4..])
{
dl += (byte)c;
}
ecx = (uint)(dl << 24) | (uint)(dl << 16) | (uint)(dl << 8) | dl;
userBytes = Encoding.ASCII.GetBytes(user[..4]);
eax = BitConverter.ToUInt32(userBytes, 0);
ecx ^= eax;
ecx = BSwap(ecx);
ecx += 0x3022006;
ecx = BSwap(ecx);
ecx -= 0xDEADC0DE;
ecx = BSwap(ecx);
cl = (byte)((ecx & 0xFF) + 1);
ecx = (ecx & 0xFFFFFF00) | cl;
ch = (byte)(((ecx >> 8) & 0xFF) + 1);
ecx = (ecx & 0xFFFF00FF) | ((uint)ch << 8);
ecx = BSwap(ecx);
cl = (byte)((ecx & 0xFF) - 1);
ecx = (ecx & 0xFFFFFF00) | cl;
ch = (byte)(((ecx >> 8) & 0xFF) - 1);
ecx = (ecx & 0xFFFF00FF) | ((uint)ch << 8);
ecx = BSwap(ecx);
ecx ^= 0xEDB88320;
ecx = BSwap(ecx);
ecx += 0xD76AA478;
ecx = BSwap(ecx);
ecx -= 0xB00BFACE;
ecx = BSwap(ecx);
ecx += 0xBADBEEF;
ecx = BSwap(ecx);
ecx++;
ecx = BSwap(ecx);
ecx--;
ecx = BSwap(ecx);
ecx += eax;
ecx = BSwap(ecx);
cx = (ushort)((ecx & 0xFFFF) + 1);
ecx = (ecx & 0xFFFF0000) | cx;
ecx = BSwap(ecx);
cx = (ushort)((ecx & 0xFFFF) + 1);
ecx = (ecx & 0xFFFF0000) | cx;
ecx = BSwap(ecx); //true serial result
//开始反向计算Serial
eax = BSwap(ecx);
int[] key = [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF];
int keyIndex = key.Length - 1;
byte[] byteArray = new byte[4];
for (int i = 3; i >= 0; i--)
{
byte temp = (byte)(eax & 0xFF);
temp = (byte)(temp - key[keyIndex--]);
temp = (byte)(temp ^ key[keyIndex--]);
byteArray[i] = temp;
eax >>= 8;
}
Console.WriteLine($"Serial: {BitConverter.ToString(byteArray).Replace("-", "")}");
}
public static bool Check(string user, string serial)
{
if (!(CheckStrLen(serial, 8, 8) && CheckStrLen(user, 5, 0)))
return false;
uint eax, ebx, ecx;
ushort cx;
byte cl, ch, dl = 0, bl;
byte[] userBytes, serialBytes;
foreach (char c in user[4..])
{
dl += (byte)c;
}
ecx = (uint)(dl << 24) | (uint)(dl << 16) | (uint)(dl << 8) | dl;
userBytes = Encoding.ASCII.GetBytes(user[..4]);
eax = BitConverter.ToUInt32(userBytes, 0);
ecx ^= eax;
ecx = BSwap(ecx);
ecx += 0x3022006;
ecx = BSwap(ecx);
ecx -= 0xDEADC0DE;
ecx = BSwap(ecx);
cl = (byte)((ecx & 0xFF) + 1);
ecx = (ecx & 0xFFFFFF00) | cl;
ch = (byte)(((ecx >> 8) & 0xFF) + 1);
ecx = (ecx & 0xFFFF00FF) | ((uint)ch << 8);
ecx = BSwap(ecx);
cl = (byte)((ecx & 0xFF) - 1);
ecx = (ecx & 0xFFFFFF00) | cl;
ch = (byte)(((ecx >> 8) & 0xFF) - 1);
ecx = (ecx & 0xFFFF00FF) | ((uint)ch << 8);
ecx = BSwap(ecx);
ecx ^= 0xEDB88320;
ecx = BSwap(ecx);
ecx += 0xD76AA478;
ecx = BSwap(ecx);
ecx -= 0xB00BFACE;
ecx = BSwap(ecx);
ecx += 0xBADBEEF;
ecx = BSwap(ecx);
ecx++;
ecx = BSwap(ecx);
ecx--;
ecx = BSwap(ecx);
ecx += eax;
ecx = BSwap(ecx);
cx = (ushort)((ecx & 0xFFFF) + 1);
ecx = (ecx & 0xFFFF0000) | cx;
ecx = BSwap(ecx);
cx = (ushort)((ecx & 0xFFFF) + 1);
ecx = (ecx & 0xFFFF0000) | cx;
ecx = BSwap(ecx); //true serial result
serialBytes = ParseHstr(serial);
ebx = (uint)(serialBytes[0] * 0x10 + serialBytes[1]);
bl = (byte)(ebx & 0xFF);
bl = (byte)((bl ^ 0x12) + 0x34);
ebx = bl;
eax = ebx;
eax <<= 8;
ebx = (uint)(serialBytes[2] * 0x10 + serialBytes[3]);
bl = (byte)(ebx & 0xFF);
bl = (byte)((bl ^ 0x56) + 0x78);
ebx = bl;
eax += ebx;
eax <<= 8;
ebx = (uint)(serialBytes[4] * 0x10 + serialBytes[5]);
bl = (byte)(ebx & 0xFF);
bl = (byte)((bl ^ 0x90) + 0xAB);
ebx = bl;
eax += ebx;
eax <<= 8;
ebx = (uint)(serialBytes[6] * 0x10 + serialBytes[7]);
bl = (byte)(ebx & 0xFF);
bl = (byte)((bl ^ 0xCD) + 0xEF);
ebx = bl;
eax += ebx;
eax = BSwap(eax); //user input serial result
return eax == ecx; //ecx<->ebx(crackme)
}
public static string ReverseString(string input)
{
if (input == null)
throw new ArgumentNullException(nameof(input), "Input string cannot be null.");
return new string(input.Reverse().ToArray());
}
public static bool CheckStrLen(string input, int min, int max)
{
int l = input.Length;
if (min > 0 && l < min)
return false;
if (max > 0 && l > max)
return false;
return true;
}
public static uint BSwap(uint value)
{
byte[] bytes = BitConverter.GetBytes(value);
Array.Reverse(bytes);
return BitConverter.ToUInt32(bytes, 0);
}
public static byte[] ParseHstr(string hexString)
{
byte[] bytes = new byte[hexString.Length];
for (int i = 0; i < hexString.Length; i++)
{
if (byte.TryParse(hexString[i].ToString(), NumberStyles.HexNumber, null, out byte value))
bytes[i] = value;
else
throw new FormatException("Invalid hex string.");
}
return bytes;
}
}