• 也谈.Net中间语言——破解Delphi2CS行数和时间限制


      其实我一直在研究将Delphi版的传奇2源代码使用C#实现,不过由于我并没有学习过Delphi。就只能说先试着用一些工具转换代码。

      后来我在网上找到了一款软件:Delphi2CS。这款软件比较强大,虽然不支持条件编译,但竟然能对窗体控件达到非常高的转换效率!且直接生成vs.net的项目,令我十分高兴,这意味着我们只需要修复很少的部分。

      不过真正尝试转换的时候发现有一个限制:源文件不得超过500行。

      如下,图片为准换完成后的报告,代码为转换完成后的cs文件:

     1 using System;
     2 using System.IO;
     3 using DCPconst;
     4 using Base64;
     5 using Sha1;
     6 
     7 namespace DCPcrypt
     8 {
     9  // Delphi2CS trial converts the .PAS file that is less than 500 lines. 
    10  // DCPcrypt.pas is 1029 lines. 
    11  // Please purchse the final version to avoid the limitation.
    12 }

      这令我十分困扰。

      后来在网上发现博客园的liufei同学解决了这个问题,他说明了方法并提供了可用程序。

      使用他的程序确实可以达到效果,但是另一个问题却出现了:

        

      大概意思是说过期了。我是从官网上下载了文件进行安装,然后将liufei同学的破解文件放到程序目录下执行的(如果是直接使用liu同学的程序是可行的)。不过出现了上图的情况。

      虽然不知道原因,不过貌似现在只能自己来破解了。

      先打开IL,载入程序

      

      

      然后依次点击“文件”=>“转储”,使用默认设置就行了

      

      然后打开il文件开始找,不过没什么挑战性,一下就找到了

      

      上述代码可用.NET Reflector还原

      1 public void F()
      2 {
      3     if (!this.TB)
      4     {
      5         try
      6         {
      7             DC.Q = this;
      8             StringBuilder builder = new StringBuilder();
      9             bool flag = false;
     10             StringBuilder builder2 = new StringBuilder();
     11             bool flag2 = false;
     12             StringBuilder builder3 = new StringBuilder();
     13             StringBuilder b = null;
     14             if (this.R != null)
     15             {
     16                 AB ab = null;
     17                 foreach (string str in this.R)
     18                 {
     19                     ab = this.NB.BB(str);
     20                     if (ab != null)
     21                     {
     22                         this.U(this.LD(ab.O()), null);
     23                     }
     24                 }
     25             }
     26             if (this.OB != null)
     27             {
     28                 foreach (string str2 in this.OB)
     29                 {
     30                     if (!str2.Equals(this.O()))
     31                     {
     32                         builder.Append("using ").Append(str2).Append(";").Append("
    ");
     33                     }
     34                 }
     35             }
     36             string str3 = SB.U();
     37             if ((str3 != null) && (str3 != ""))
     38             {
     39                 builder.Append(str3);
     40             }
     41             if (this.EB != null)
     42             {
     43                 builder.Append(this.EB.Replace("U_K_N_O_W_N ", " "));
     44             }
     45             if (QB.B != 100)
     46             {
     47                 this.ED("Delphi2CS has expired.");
     48                 builder3.Append("// Delphi2CS has expired, please purchase the final version. 
    ");
     49                 flag = true;
     50             }
     51             else if (this.GB.A > 0x1f4)
     52             {
     53                 this.ED("Delphi2CS trial converts the .pas file that is less than 500 lines.");
     54                 builder3.Append(" // Delphi2CS trial converts the .PAS file that is less than 500 lines. 
    ");
     55                 string fileName = Path.GetFileName(this.O);
     56                 builder3.Append(string.Concat(new object[] { " // ", fileName, " is ", this.GB.A, " lines. 
    " }));
     57                 builder3.Append(" // Please purchse the final version to avoid the limitation.
    ");
     58                 flag = true;
     59             }
     60             if (!flag)
     61             {
     62                 if ((this.MB != null) && (this.MB.Count > 0))
     63                 {
     64                     foreach (YB yb in this.MB.ToArray())
     65                     {
     66                         if (yb.L() == null)
     67                         {
     68                             continue;
     69                         }
     70                         if (SB.J())
     71                         {
     72                             if (b == null)
     73                             {
     74                                 b = new StringBuilder();
     75                             }
     76                             b.Append("namespace " + this.O() + "
    {").Append("
    ");
     77                             b.Append("  partial class ").Append(yb.B.A).Append("
    ");
     78                             b.Append("    {
    ");
     79                             b.Append(yb.L().U());
     80                             b.Append("    }
    ");
     81                             b.Append("}
    ");
     82                         }
     83                         builder3.Append(yb.HB());
     84                         this.MB.Remove(yb);
     85                     }
     86                 }
     87                 if ((this.MB != null) && (this.MB.Count > 0))
     88                 {
     89                     foreach (YB yb2 in this.MB)
     90                     {
     91                         builder3.Append(yb2.HB());
     92                     }
     93                 }
     94                 if (this.U.K.W != null)
     95                 {
     96                     flag2 = true;
     97                     StringBuilder builder5 = new StringBuilder();
     98                     builder5.Append(this.U.K.W.FB());
     99                     if (builder5.Length > 0)
    100                     {
    101                         builder2.Append("namespace ").Append(this.O()).Append(".Units
    ");
    102                         builder2.Append("{
    ");
    103                         builder2.Append(builder5.ToString());
    104                         builder2.Append("}
    ");
    105                         builder2.Append("
    ");
    106                         string str5 = this.HB();
    107                         if (str5 != null)
    108                         {
    109                             str5 = str5.Replace("U_K_N_O_W_N ", "");
    110                             builder2.Append(str5);
    111                         }
    112                     }
    113                 }
    114             }
    115             string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(this.O);
    116             string a = fileNameWithoutExtension + ".Designer.cs";
    117             if (this.RB)
    118             {
    119                 string str8 = this.NB.LB(this.O);
    120                 fileNameWithoutExtension = fileNameWithoutExtension + str8;
    121             }
    122             else
    123             {
    124                 fileNameWithoutExtension = fileNameWithoutExtension + ".cs";
    125             }
    126             string str9 = this.O.ToLower().Replace(this.NB.K, this.NB.J);
    127             if (!str9.StartsWith(this.NB.J))
    128             {
    129                 str9 = this.NB.J(str9, this.NB.J);
    130             }
    131             if (!str9.StartsWith(this.NB.J))
    132             {
    133                 str9 = this.NB.K(str9, this.NB.J);
    134             }
    135             str9 = Path.Combine(Path.GetDirectoryName(str9), fileNameWithoutExtension);
    136             FileInfo info = new FileInfo(str9);
    137             if (info.Exists)
    138             {
    139                 info.Delete();
    140             }
    141             else
    142             {
    143                 info.Directory.Create();
    144             }
    145             this.PC();
    146             FileStream stream = info.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
    147             StreamWriter writer = new StreamWriter(stream, Encoding.Default);
    148             writer.Write(builder.ToString());
    149             if (builder3.Length > 0)
    150             {
    151                 writer.WriteLine("namespace " + this.O() + "
    {");
    152                 writer.Write(builder3.ToString());
    153                 writer.WriteLine("}
    ");
    154             }
    155             if (flag2)
    156             {
    157                 writer.Write(builder2.ToString());
    158             }
    159             writer.Close();
    160             stream.Close();
    161             writer = null;
    162             stream = null;
    163             if ((b != null) && (b.Length > 0))
    164             {
    165                 this.VC(a, b);
    166             }
    167             builder2 = null;
    168             builder3 = null;
    169             builder = null;
    170             this.P = str9.Replace(this.NB.J, "");
    171             if (this.P.StartsWith(Path.DirectorySeparatorChar.ToString()))
    172             {
    173                 this.P = this.P.Substring(1);
    174             }
    175             this.NB.T.Add(this.P);
    176             if (this.KB != null)
    177             {
    178                 string key = this.KB.Replace(this.NB.J, "");
    179                 this.JC("Creating " + Path.GetFileName(this.KB));
    180                 try
    181                 {
    182                     this.LB.Close();
    183                     this.NB.U.Add(key, this.P);
    184                 }
    185                 catch
    186                 {
    187                 }
    188             }
    189         }
    190         catch (Exception exception)
    191         {
    192             this.NB.W(exception.ToString());
    193             this.ED(exception.Message);
    194         }
    195     }
    196 }

      上面的语句其实是一个条件判断,判断读取到的行数是否小于500,在第51行处。我们可以改到500000。

      行数限制似乎破解了,那么时间限制呢?文章第一副图片所示大概是说我们使用的是Delphi2CS评估版,而现在它过期了。

      破解过期时间很简单,我们在il文件中找到过期判断语句

     1 .method private hidebysig instance void 
     2           H(object A,
     3             class [mscorlib]System.EventArgs B) cil managed
     4   {
     5     // 代码大小       435 (0x1b3)
     6     .maxstack  4
     7     .locals init (string V_0,
     8              string V_1,
     9              class [mscorlib]System.Threading.ThreadStart V_2,
    10              class [mscorlib]System.Threading.Thread V_3)
    11     IL_0000:  ldsfld     int32 QB::B
    12     IL_0005:  ldc.i4.s   100
    13     IL_0007:  beq.s      IL_001d
    14 
    15     IL_0009:  ldstr      "Delphi2CS Evaluation Version has expired, please p"
    16     + "urchase the final version."
    17     IL_000e:  ldstr      "Error"
    18     IL_0013:  ldc.i4.0
    19     IL_0014:  ldc.i4.s   16

      搜索“Delphi2CS Evaluation”即可找到,上面代码第11行即判断了QB.B和100是否相等,我们通过.NET Reflector来查看可得下面的代码:

     1 private void H(object A, EventArgs B)
     2 {
     3     if (QB.B != 100)
     4     {
     5         MessageBox.Show("Delphi2CS Evaluation Version has expired, please purchase the final version.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
     6     }
     7     else
     8     {
     9         this.UB = this.O.Text;
    10         if ((this.UB.Trim().Length == 0) || (this.UB == null))
    11         {
    12             MessageBox.Show("You must input an existed Delphi Project filename", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
    13         }
    14         else if (!File.Exists(this.UB))
    15         {
    16             MessageBox.Show("You must input an existed Delphi Project filename:
     '" + this.UB + "'", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
    17         }
    18         else
    19         {
    20             this.VB = this.J.Text;
    21             if (this.VB.Trim().Length == 0)
    22             {
    23                 MessageBox.Show("Please specify an output path for the generated C# files", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
    24             }
    25             else
    26             {
    27                 if (!Directory.Exists(this.VB))
    28                 {
    29                     Directory.CreateDirectory(this.VB);
    30                 }
    31                 this.VB = Path.GetFullPath(this.VB);
    32                 if (!this.VB.EndsWith(new string(Path.DirectorySeparatorChar, 1)))
    33                 {
    34                     this.VB = this.VB + Path.DirectorySeparatorChar;
    35                 }
    36                 string str = Path.GetDirectoryName(this.UB).ToLower();
    37                 string str2 = Path.GetDirectoryName(this.VB).ToLower();
    38                 if (str.StartsWith(str2))
    39                 {
    40                     MessageBox.Show("Please make sure the Output path is different from the project path.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Hand);
    41                 }
    42                 else
    43                 {
    44                     this.WB = new LD(this);
    45                     ThreadStart start = new ThreadStart(this.I);
    46                     Thread thread = new Thread(start);
    47                     thread.Start();
    48                     this.WB.ShowDialog(this);
    49                     try
    50                     {
    51                         if (thread != null)
    52                         {
    53                             thread.Abort();
    54                         }
    55                         else
    56                         {
    57                             thread = null;
    58                         }
    59                     }
    60                     catch
    61                     {
    62                     }
    63                     this.WB = null;
    64                     base.Activate();
    65                 }
    66             }
    67         }
    68     }
    69 }

      其实能够猜到:这个方法是点击浏览按钮选择了文件后的事件处理方法。第一步就判断了QB.B是否等于100,如果不等的话就会终端执行。我们只需把if的条件设为永远不等即可,如下面这样

     1 .method private hidebysig instance void 
     2           H(object A,
     3             class [mscorlib]System.EventArgs B) cil managed
     4   {
     5     // 代码大小       435 (0x1b3)
     6     .maxstack  4
     7     .locals init (string V_0,
     8              string V_1,
     9              class [mscorlib]System.Threading.ThreadStart V_2,
    10              class [mscorlib]System.Threading.Thread V_3)
    11     IL_0000:  ldc.i4.s   100
    12     IL_0005:  ldc.i4.s   100
    13     IL_0007:  beq.s      IL_001d
    14 
    15     IL_0009:  ldstr      "Delphi2CS Evaluation Version has expired, please p"
    16     + "urchase the final version."
    17     IL_000e:  ldstr      "Error"
    18     IL_0013:  ldc.i4.0
    19     IL_0014:  ldc.i4.s   16

      在IL_0000里我把二元判断表达式左边的值从QB.B直接换成了100,这样的话就不存在过期了,因为if(100 != 100)永远为false!

      其实现在要做的就很简单了,把上面的0x1f4(即500)改大和把这个使用了QB.B判断并终止程序执行的地方修正(其实重要的地方有两个,上述的KD.H方法中和BB.F中,后者的if判断正在500行判断前)。我更改过后后进入vs.net的命令行生成可执行文件。

      

      

      按照liu同学的说法,delphi2cs程序需要.net framework3.5,所以vs2005的cmd无法编译,不过我没有尝试。按照上图的方法就能生成exe文件了,使用生成的文件替换掉安装目录下文件即可。

      我把破解了的文件上传上来,大家可以看看。

     欢迎您移步我们的交流群,无聊的时候大家一起打发时间:Programmer Union

     或者通过QQ与我联系:点击这里给我发消息

     (最后编辑时间2013-08-17 01:05:38)

  • 相关阅读:
    利用.net Core 对程序集中的类 进行统一依赖注入
    接口中定义异步的方法
    在efcore 中创建类 通过实现IEntityTypeConfiguration<T>接口 实现实体类的伙伴类 实现FluentApi
    在vs2017 版本15.7.6中不支持2.1.0以上版本的net core sdk
    在.net core不同的版本中 webabi引用的包不同
    SQL语句中使用Group by
    DDD实战12 值对象不创建表,而是直接作为实体中的字段
    src与href的区别。
    cookies,sessionStorage 和 localStorage 的区别
    javascript阻止事件冒泡和浏览器的默认行为
  • 原文地址:https://www.cnblogs.com/Johness/p/3262136.html
Copyright © 2020-2023  润新知