207 lines
6.2 KiB
C#
207 lines
6.2 KiB
C#
|
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;
|
|||
|
}
|
|||
|
}
|