| 
前情提要学习总结
×
注册登录后全站资源免费查看下载您需要 登录 才可以下载或查看,没有账号?立即注册  乍一看大佬的帖子一头雾水,相信也吓退了一部分小白,下面先总结一下,提取一下关键点,前贴总共介绍了2种Patch的方法: 1、使用内部自带的注册码 此时license是“GrapeCity-Internal-License”开头,需要验证调用程序的签名,如果不是指定范围内的程序,则会触发异常。复制代码 隐藏代码 //amj.l(A_0)internal bool a(string A_0){    return A_0 != null && A_0.StartsWith("GrapeCity-Internal-License,", StringComparison.Ordinal);}//amj.j(A_1)internal bool a(object A_0){    Assembly assembly = A_0 as Assembly;    if (A_0 == null)    {            return false;    }    byte[] publicKeyToken = assembly.GetName().GetPublicKeyToken();    ulong num = 0UL;    if (publicKeyToken == null)    {            return false;    }    for (int i = 0; i < publicKeyToken.Length; i++)    {            num = (num << 8) | (ulong)publicKeyToken;    }    return new HashSet<ulong> { 8757299328925775578UL, 10685601461268105732UL, 15833087347736823688UL, 11201956651387526890UL, 7968347106218921853UL }.Contains(num);}
 Patch此处函数a,返回true即可。 2、通过伪造key复制代码 隐藏代码 internal static string GetLicense(Type t){    string name = "52pojie";    var temp = new    {        S = Convert.ToBase64String(Encoding.UTF8.GetBytes("0")),        D = new        {            Id = name,            Prd = new[]            {                new {N = "WU5D", C = "WU5D"}            },            Crt = DateTime.Now.ToString("yyyyMMdd hhmmss", CultureInfo.InvariantCulture)        }    };    string json = JsonConvert.SerializeObject(temp);    string lic = (string)t.Assembly.GetType("GrapeCity.Documents.Excel.sp").GetMethod("g").Invoke(null, new object?[] { json }); ;    return $"{name}#A0{lic}";}
 其中的参数“S”就是数据的签名信息,因为“S”不正确,验签时VerifyData函数不能通过,此时Patch该函数返回true也可以达到目的。复制代码 隐藏代码 // this.d('s').a() -> so("wE+VWE4exHP+ieziZg+Cgf7sJslBhVzJbPXZQwfGUfU27NqODPzCpizjAPz6NnKw8GCiHpug6D+bUxmutcBmUw==", "AQAB").a() -> RSA鉴权internal class so{    // Token: 0x060031AD RID: 12717 RVA: 0x001EE44C File Offset: 0x001EC64C    public so(string A_0, string A_1)    {            this.a.ImportParameters(new RSAParameters            {                    Modulus = Convert.FromBase64String(A_0),                    Exponent = Convert.FromBase64String(A_1 ?? "AQAB")            });    }    // Token: 0x060031AE RID: 12718 RVA: 0x001EE4A1 File Offset: 0x001EC6A1    public bool a(string A_0, string A_1)    {                            return !string.IsNullOrEmpty(A_1) && this.a.VerifyData(Encoding.UTF8.GetBytes(A_0), "SHA1", Convert.FromBase64String(A_1));    }    // Token: 0x04001503 RID: 5379    private readonly RSACryptoServiceProvider a = new RSACryptoServiceProvider();}终极目标---注册码(注册机)
 1、RSA加解密介绍 从验证方式看,本插件用的是RSA非对称加解密。数据加签是RSA加解密的基本操作,钥匙对包含公钥和私钥,通常私钥加签,公钥解密,所以通常公钥是公开的,私钥作者持有,不会公开。 2、本软件的公钥信息复制代码 隐藏代码("wE+VWE4exHP+ieziZg+Cgf7sJslBhVzJbPXZQwfGUfU27NqODPzCpizjAPz6NnKw8GCiHpug6D+bUxmutcBmUw==", "AQAB"),看看长度:
 string m = "wE+VWE4exHP+ieziZg+Cgf7sJslBhVzJbPXZQwfGUfU27NqODPzCpizjAPz6NnKw8GCiHpug6D+bUxmutcBmUw==";        RSACryptoServiceProvider rsp = new RSACryptoServiceProvider();        rsp.ImportParameters(new RSAParameters        {            Modulus = Convert.FromBase64String(m),            Exponent = Convert.FromBase64String("AQAB")        });        int keysize = rsp.KeySize;//512位
 根据网上大佬的经验总结,512及以下位数的key是可以通过因式分解求得私钥的(超过512位就先止步吧)。经过三七四十九天的分解,终于分解成功拿到私钥了。有了私钥是生成注册码的关键和基础。 3、分析加签过程 由上面分析可知,要想生成注册码,只需要对注册数据加签并写到参数“S”中即可。原内部key:"GrapeCity-Internal-License,296578427539473#A0GSMwWZjhXRgI7bmBCduVWb5N6bEByQHJiOi8kI1tlOiQmcQJCLiQDN9UjMwASNxATMwIDMyIiOiQncDJCLikHdpNUZwFmcHJiOiEmTDJCLiMzN4kzM5cjM4gzN5YTOyIiOiQWSisnOiQkIsISP3cXVqtiN9kFWwc5LVZTV5VmZFdWM5xUOolWNrdHNpxUV7MzSnhDWEllS8oHc6V5T8AzMmhjSxJVMUpWeZZlQyYnY6BTVHZzS6RnS9clTYJUcht6dDJEaiojITJCL5AzN8EjM6MTN0IicfJye#4Xfd5nINJDOZJiOiMkIsICN6BCdl9kLgwWZjhXRgI7bmBCduVWb5N6bEByQHJiOi8kI1xSfiM5VNNlI0IyQiwiI4YHI4VmTuAyZul6Zh5WSgI7bmBCduVWb5N6bEByQHJiOi8kI1xSfig4UXFlI0IyQiwiI4YHI4VmTuAiZkBFIy3mZgQnbl5Wdj3GRgM4RiojIOJyes4nI4IUULJiOiMkIsICN6BCdl9kLgQmcvdFIy3mZgQnbl5Wdj3GRgM4RiojIOJyes4nIFx4REJiOiMkIsICN6B3YsF"
 
  将key用字符串“#A0”分割成2部分,后一部分解密:
 
  复制代码 隐藏代码
 {    "_r": 536218705,    "S": "hBCwkaqBXNW9JtvK6GU0vbv2BVYyjT1RqJ8f308OUvpz8JYDX8gK37ULi4wk5ih9Lu1gEfeuU6U/W0XY96+jUw==",    "D": {        "Id": "296578427539473",        "CNa": "GrapeCity",        "Crt": "20201015 025944",        "Prd": [{            "N": "GC Document for Excel Java v4",            "C": "DGLE"        }, {            "N": "GC Document for Word .Net v4",            "C": "KQB4"        }, {            "N": "GC Document for Pdf .Net v4",            "C": "QWSH"        }, {            "N": "GC Document for Imaging .Net v4",            "C": "SMWS"        }, {            "N": "GC Document for Excel .Net v4",            "C": "Y82M"        }]    }}
 其中“S”为签名信息,“D”为授权信息。 授权信息构成:复制代码 隐藏代码 public static string a(this sj A_0)    {        if (A_0 == null)        {            return "";        }        StringBuilder stringBuilder = new StringBuilder();        using (StringWriter stringWriter = new StringWriter(stringBuilder, CultureInfo.InvariantCulture))        {            stringWriter.Write("{");            if (A_0.a() != null)            {                stringWriter.Write("\"{0}\":", "Anl");                stringWriter.Write("{");                stringWriter.Write("\"{0}\":{1}", "dsr", Convert.ToString(A_0.a().Value).ToLowerInvariant());                stringWriter.Write("},");            }            stringWriter.Write("\"{0}\":\"{1}\",", "Id", A_0.k());//必须项            if (A_0.j())            {                stringWriter.Write("\"{0}\":{1},", "Evl", Convert.ToString(A_0.j()).ToLowerInvariant());            }            if (!string.IsNullOrEmpty(A_0.i()))            {                stringWriter.Write("\"{0}\":\"{1}\",", "OId", A_0.i());            }            if (!string.IsNullOrEmpty(A_0.h()))            {                stringWriter.Write("\"{0}\":\"{1}\",", "CNa", A_0.h());            }            if (!string.IsNullOrEmpty(A_0.g()))            {                stringWriter.Write("\"{0}\":\"{1}\",", "CId", A_0.g());            }            if (!string.IsNullOrEmpty(A_0.f()))            {                stringWriter.Write("\"{0}\":\"{1}\",", "Dms", A_0.f());            }            if (!string.IsNullOrEmpty(A_0.e()))            {                stringWriter.Write("\"{0}\":\"{1}\",", "Ips", A_0.e());            }            if (A_0.d() != null)            {                stringWriter.Write("\"{0}\":\"{1}\",", "Exp", A_0.d().Value.ToString("yyyyMMdd", CultureInfo.InvariantCulture));            }            stringWriter.Write("\"{0}\":\"{1}\",", "Crt", A_0.c().ToString("yyyyMMdd hhmmss", CultureInfo.InvariantCulture));//必须项            stringWriter.Write("\"{0}\":[{1}]", "Prd", string.Join(",", A_0.b().Select(new Func<sk, string>(sn.<>c.<>9.a))));//必须项            stringWriter.Write("}");        }        return stringBuilder.ToString();    }
 由上可知仅有Id,Crt和Prd三项必须,其余可无,若有必须按照上面的顺序。这也是之前大佬构造key的基础。复制代码 隐藏代码 string name = "52pojie";    var temp = new    {        S = Convert.ToBase64String(Encoding.UTF8.GetBytes("0")),        D = new        {            Id = name,            Prd = new[]            {                new {N = "WU5D", C = "WU5D"}            },            Crt = DateTime.Now.ToString("yyyyMMdd hhmmss", CultureInfo.InvariantCulture)        }    };
 4、注册码(注册机) 根据以上分析可以写出注册机,生成注册码:验签数据=第一部分数据 + 分隔符("#A0") + D(授权信息),然后根据RSA的加签函数(此处需要用到前面提到的私钥)生成签名信息S。最/后再加密生成注册码。
 
  
 
 5、可用key及使用方法 提供一组可用key,设置了有效期:2023-12-31,直接使用如下:复制代码 隐藏代码 string license=@"52pojie#A0iiW34TQxo7NQ9EMUNUV9pmY5M6c7gEexJXQrIkbpdlbvIXO7l5ZtFUcPlldHZ6MzdnSJpXe8dTe92mbrMGaQdjUQlGehVWTD5kbTNXaWlnNVV6RqVDbRljcnJiOiMlIsIiN6YjN6YjI0IicfJye&Qf35VfiQUNVdlI0IyQiwiIsV6Y8VkI0IiTis7W0ICZyBlIsICMwADMyEDI5EDNwMjMwIjI0ICdyNkIsISMzITMzIDMyIiOiAHeFJCLiIjMxMHciojIh94QiwiI8gDO8gDO8gjI0ICZJJye0rCii";Workbook workbook = new GrapeCity.Documents.Excel.Workbook(license);IWorksheet worksheet = workbook.Worksheets[0];worksheet.Cells[0].Value = "Hell0 worsddf";workbook.Save("test.xlsx");
 搞定~~~注意事项 仅限于学习交流,请勿用于商业或非法用途。 转载自吾爱破/解哦! 
 |