首页
论坛
专栏
课程

[.NET平台] [分享]ReSharper破解过程

2016-7-5 23:17 12349

[.NET平台] [分享]ReSharper破解过程

2016-7-5 23:17
12349
ReSharper一直以来以c#的插件闻名, 最近发现他新出的c++插件也挺好用的,就是代码提示有点慢。他的插件都是.net实现的, 之前没搞过.net破解, 把学习过程跟大家分享下

大概是因为性能考虑, 他的代码没有混淆,直接用ILSpy 看,对照写一个假的处理函数,生成假dll,分别用ILDasm导出 假dll 和 原始dll 的IL代码, 然后替换,再用ILAsm编译回去替换就好了。

因为逻辑较多,废了很长时间才找到他的注册码处理函数DecodeLicense 
中间试过动态调试, 结果ILSpy的debugger插件attach不上vs, PEBrowser也各种出错,最后只能用在假dll加 Trace.WriteLine 的方法打印出流程, 及找出代码修改的问题
// JetBrains.Application.License2.NewLicenses.UserLicenseService
public NewLicenseData DecodeLicense(string base64)
{
  return Logger.CatchIgnore<NewLicenseData>(delegate
  {
    List<StringSlice> list = new StringSlice(base64).Trim().Split(new char[]
    {
      '-'
    }).ToList<StringSlice>();
    if (list.Count != 4)
    {
      return null;
    }
    StringSlice stringSlice = list[0];
    StringSlice stringSlice2 = list[1];
    StringSlice stringSlice3 = list[2];
    StringSlice stringSlice4 = list[3];
    byte[] left = MD5.Create().ComputeHash(this.RootCertificate.RawData);
    byte[] right = new byte[]
    {
      75,
      251,
      173,
      56,
      28,
      192,
      192,
      50,
      63,
      169,
      145,
      143,
      230,
      144,
      67,
      120
    };
    if (!left.EqualEnumerables(right))
    {
      return null;
    }
    byte[] rawData = Convert.FromBase64String(stringSlice4.ToString());
    X509Certificate2 x509Certificate = new X509Certificate2(rawData);
    if (!UserLicenseService.VerifyCertificate(x509Certificate, new X509Certificate2[]
    {
      this.RootCertificate
    }))
    {
      return null;
    }
    if (this.RevocedCertificateSerialNumbers.Contains(x509Certificate.SerialNumber))
    {
      return null;
    }
    byte[] bytes = Convert.FromBase64String(stringSlice2.ToString());
    string @string = Encoding.UTF8.GetString(bytes);
    if (!UserLicenseService.VerifySignature(@string, stringSlice3.ToString(), x509Certificate))
    {
      return null;
    }
    NewLicenseData newLicenseData = NewLicenseData.FromJson(@string);
    if (newLicenseData != null && !stringSlice.Equals(newLicenseData.LicenseId))
    {
      return null;
    }
    return newLicenseData;
  });
}



之前有人破解是将程序里的证书替换成自己的证书来验证License,但新版本里给证书加了md5验证,写死在代码里。 当然也可以改这个写死的md5码,不过既然改程序了,不如都改了,
改成直接创建NewLicenseData返回。 

// JetBrains.Application.License2.NewLicenses.UserLicenseService
public NewLicenseData DecodeLicense(string base64)
{
  return Logger.CatchIgnore<NewLicenseData>(() => new NewLicenseData
  {
    LicenseId = "1",
    LicenseeName = "Raven",
    AssigneeName = "Raven-PC",
    LicenseRestriction = null,
    CheckConcurrentUse = false,
    AutoProlongated = true,
    Hash = "",
    GracePeriodDays = 0,
    Products = new List<ProductData>
    {
      new ProductData
      {
        Code = "RSU",
        FallbackDate = DateTime.MinValue,
        PaidUpTo = DateTime.MaxValue
      },
      new ProductData
      {
        Code = "DM",
        FallbackDate = DateTime.MinValue,
        PaidUpTo = DateTime.MaxValue
      },
      new ProductData
      {
        Code = "II",
        FallbackDate = DateTime.MinValue,
        PaidUpTo = DateTime.MaxValue
      },
      new ProductData
      {
        Code = "AC",
        FallbackDate = DateTime.MinValue,
        PaidUpTo = DateTime.MaxValue
      },
      new ProductData
      {
        Code = "CL",
        FallbackDate = DateTime.MinValue,
        PaidUpTo = DateTime.MaxValue
      },
      new ProductData
      {
        Code = "DB",
        FallbackDate = DateTime.MinValue,
        PaidUpTo = DateTime.MaxValue
      },
      new ProductData
      {
        Code = "PS",
        FallbackDate = DateTime.MinValue,
        PaidUpTo = DateTime.MaxValue
      },
      new ProductData
      {
        Code = "PC",
        FallbackDate = DateTime.MinValue,
        PaidUpTo = DateTime.MaxValue
      },
      new ProductData
      {
        Code = "RM",
        FallbackDate = DateTime.MinValue,
        PaidUpTo = DateTime.MaxValue
      },
      new ProductData
      {
        Code = "WS",
        FallbackDate = DateTime.MinValue,
        PaidUpTo = DateTime.MaxValue
      }
    }
  });
}


最后发现这个dll有强名称验证

 可以把因为这个dll的assembly的引用改掉,不过因为这个dll引用太多了,改起来比较麻烦, 我采取了比较极端的方式,直接改clr 里的强名称验证函数

BOOLEAN __stdcall StrongNameSignatureVerification(LPCWSTR wszFilePath, DWORD dwInFlags, DWORD *pdwOutFlags)
{
  BOOLEAN v3; // bl@1
  int v4; // esi@2
  int *v5; // eax@2
  int v6; // ecx@2
  int v7; // esi@7
  _DWORD *v9; // eax@17
  _DWORD *v10; // eax@20
  char v11; // [sp+14h] [bp-40h]@9
  char v12; // [sp+1Ch] [bp-38h]@2
  char v13; // [sp+3Ch] [bp-18h]@6
  int v14; // [sp+50h] [bp-4h]@2

  v3 = 1;
  if ( !byte_1064D308 )
    goto LABEL_2;
  if ( dword_1065D0D0(12) )
  {
    if ( byte_1064D308 )
      sub_1042876E(&v11);
LABEL_2:
    v14 = 0;
    memset(&v12, 0, 0x28u);
    v4 = sub_100CA6D3();
    v5 = (int *)sub_100CA6E5();
    if ( v4 >= 0 )
    {
      if ( v5 )
        *v5 = 0;
      if ( !wszFilePath )
      {
        v9 = (_DWORD *)sub_100CA6E5();
        if ( v9 )
          *v9 = -2147467261;
        goto LABEL_19;
      }
      v13 = 1;
      if ( (unsigned __int8)sub_1009DEAE(&v12, v6, 1) )
      {
        v7 = sub_1009D71C(&pbEcmaPublicKey, pdwOutFlags);
        if ( v7 < 0 )
        {
          v10 = (_DWORD *)sub_100CA6E5();
          if ( v10 )
            *v10 = v7;
          v3 = 0; // 这里
        }
        if ( (unsigned __int8)sub_1009DC2A(&v12) )
          goto LABEL_9;
        if ( !v3 )
        {
LABEL_19:
          v3 = 0; // 这里
LABEL_9:
          v11 = 0;
          v14 = -1;
          if ( byte_1064D308 )
            sub_10428786(&v11);
          return v3;
        }
      }
      v4 = sub_100C6DFA();
      v5 = (int *)sub_100CA6E5();
    }
    if ( v5 )
      *v5 = v4;
    goto LABEL_19;
  }
  if ( dword_1065D0D4 )
    dword_1065D0D4(0);
  return v3;
}


返回值有两处被赋值为0, 改为1就好了


[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

上传的附件:
最新回复 (10)
landeaxm 2016-7-6 00:15
2
0
对应JetBrains.ReSharperUltimate.2016.1.2?
cooldogpp 2016-7-6 08:57
3
0
路过 学习了
伤落蓝羽 1 2016-7-6 09:09
4
0
是的,其他版本应该差不多
黑洛 1 2016-7-7 15:26
5
0
佔個位置,正在用Resharper,C++代碼補全確實是很好用的。
xdnice 2016-8-3 12:30
6
0
做个记号。
ttyaohui 2016-8-11 21:31
7
0
C++代碼補全確實是很好用
cutdu 2017-2-7 00:31
8
0
好文章,支持, "直接改clr 里的强名称验证函数"有点儿不爽 :)
llc1968 2017-2-7 09:50
9
0
好文,用PvLogiciels这个软件混淆过的有办法吗
方向感 2017-2-7 13:16
10
0
替换签名,再重新签名呗
wpsys 2017-2-28 21:38
11
0
谢谢分享!学习了,有你更精彩!
游客
登录 | 注册 方可回帖
返回