65.9K
CodeProject 正在变化。 阅读更多。
Home

控制演示版破解和软件盗版问题,为初学者 - 第 1 部分

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.60/5 (2投票s)

2011年7月24日

CPOL

4分钟阅读

viewsIcon

27296

downloadIcon

411

本文是为那些在发布应用程序之前真正面临演示版破解问题的小型独立开发者而写的。

引言

在本文的早期版本中,我没有提供实现所述策略的源代码。我将更新本文,包含所需的源代码行,希望这能更清楚地解释我的概念。已经阅读过本文早期版本的读者可以直接跳转到标题“为实现我们的目标,请执行以下 2 个步骤:”下的更新部分。

一家组织良好的 IT 公司有其制定软件盗版和破解问题控制策略的专家,但对于初学者和独立开发者来说,这确实是一个痛苦的问题。

应用程序演示版用于宣传目的,通常会提供一个注册选项以升级到完整版。注册是通过客户提供许可证密钥以换取自动生成的许可证代码来完成的。

这是最薄弱的环节,如果许可证密钥被破解,演示版可以轻松转换为完整版,开发者的劳动成果控制权就会落入他人手中。

控制盗版所用方法

  • 将加密狗(硬件)连接到软件
  • 提供许可证密钥用于注册以换取许可证代码

总的来说,许可证密钥选项用于此目的。因此,问题在于尝试在演示版级别控制盗版,而策略是完全将演示版与应用程序的完整版隔离开来。

在制作应用程序的演示版时,会考虑许多方面。让我们来看看它们。

  1. 演示版提供一个有限天数的到期期限。如果客户在此期限内未注册,演示版将过期。
  2. 应用程序的功能被部分保留,而不是整个应用程序。只有在注册后,客户才能使用应用程序的全部功能。
  3. 要注册,客户需要提供许可证密钥以换取自动生成的许可证代码。

因此,应用程序注册是存在最大破解风险的点。

为克服这种情况,可以采取以下策略

  1. 演示版就是演示版,不提供升级到完整版的功能。
  2. 从完整版中,剥离出演示版的独立部分,仅包含部分功能,并具有有限的到期期限。
  3. 需要添加一个额外的功能,即对每个系统允许的演示版重新安装次数有限,并且每次安装都有有限的到期天数。在完成有限次数的安装后,除非系统被格式化,否则不应重新安装演示版。

为实现第三点,可以使用一个单独的控制台应用程序来创建一个保存安装日期和安装计数器值的文件。

安装计数器应在每次演示版重新安装时增加 +1,安装日期应保持固定,用于演示版到期计算。

欺骗破解者

我们应尝试使用多种策略来保护上述文件内容不被恶意者接触。以下是一些建议

  1. 安装日期和安装计数器可以保存在单独的文件中。
  2. 可以使用多个特殊文件夹,如 *SystemRoot* 和 *Registry* 来单独存储这些文件/内容。

    例如,可以通过以下方式获取特殊文件夹“ApplicationData”的路径

    String appDataPath = Environment.GetFolderPath
    			( Environment.SpecialFolder.ApplicationData)

    可以通过以下方式获取 *SystemRoot* 路径

    String SysRtPath = Environment.GetEnvironmentVariable("SystemRoot"); 
  3. 在将安装日期存储到文件时,始终以随机格式存储,并在我们的代码需要时将其重新编译成正确格式。还可以包含一些垃圾数据来混淆。
  4. 可以采用加密策略来保护数据。

为实现我们的目标,请执行以下两个步骤

步骤 1

可以使用一个控制台应用程序来创建用于保存安装日期和重新安装计数器信息的文件。该控制台应用程序应作为主要输出附加到演示版的安装程序中,并在客户端机器上安装时执行,以存储该客户端系统的信息。

例如,如果我们想在安装过程中点击“注册”按钮时执行此文件,请在安装程序的 UI 编辑器的“注册用户对话框”的可执行属性中设置 said 控制台应用程序的“主要输出”。

请注意,以下源代码使用 *SystemRoot* 文件夹和 *Registry* 来存储我们的潜在数据文件。尽管源代码附带的帮助说明是自明的,但源代码的主要功能如下:

  • 在“SystemRoot”文件夹中存储有限安装次数的信息以及安装计数器,同时控制安装次数限制。
  • 更新每次增量安装的安装日期。
  • 将信息存储在“注册表子项”中。
  • 还插入了一些垃圾信息以迷惑破解者,程序员可以根据需要进行编辑。

源代码示例

//  Demdsthlp file
  using System;
  using  System.Collections.Generic;
  using  System.Text;
  using  Microsoft.Win32;
  using System.IO;

namespace  Demdthlp
  {
  class Program
  {
  RegistryKey  rk, rgsk;
  int d,  m, y;
  string  revdt, Dtfor_SysRt;
  string  syrtdtflpth;

  Program()
  {
  syrtdtflpth = Environment.GetEnvironmentVariable("SystemRoot");
  d = 0; m = 0; y = 0; revdt = "MPAD";
  }

  // Date formatting and making a string to store in Registry key  
  // and SystemRoot folder
  private  void md_instdt()
  {
  string  dd_num = "0";
  string  mm_num = "0";
  DateTime  dt = DateTime.Now;
  d = dt.Day;
  m = dt.Month;
  y = dt.Year;

  if  (d < 10)
  dd_num += d.ToString().Trim();
  else
  dd_num = d.ToString().Trim();

  if  (m < 10)
  mm_num += m.ToString().Trim();
  else
  mm_num = m.ToString().Trim();

  string strdt  = dd_num + mm_num + Convert.ToString(y).Trim();

  Dtfor_SysRt = strdt;

  for  (int i = 0; i < 8; i++)
  revdt += strdt.Substring(7 - i,  1);
  revdt += "NORKREV1602"; // Garbage info as strategy required
  }

  // Making a Fake Registry for above said purpose
  private void ed_rgy()
  {
  rk = Registry.CurrentUser;
  rk.DeleteSubKey("Software\\abcDem", false);
  rgsk = rk.OpenSubKey("Software", true);

  try
  {
  RegistryKey  newrk = rgsk.CreateSubKey("abcDem");
  newrk.SetValue("adem",  revdt.ToString().Trim(), RegistryValueKind.String);
  }
  catch  (Exception s)
  {
  Console.WriteLine(s.Message);
  }
  }

  // Creating  file in SystemRoot Folder
  private  void ed_sysrt()
  {
  syrtdtflpth += "\\demdt.dtd";
  if  (File.Exists(syrtdtflpth))
  {
  //  Check install counter in file
  string  insCounter = RetuInstalCounter(syrtdtflpth);
  int  ncount = int.Parse(insCounter);

  //  Counter ==5 , don't update installation date so that demo can't be renewed
  if  (ncount >= 5)
  {
  Console.WriteLine("Sorry, Your Demo Trials Limit is Over.");
  Console.ReadLine();
  return;
  }
  else
  {
  //  otherwise increase install counter by +1
  ncount++; string strcount = "";
  strcount = ncount.ToString().Trim();
  Dtfor_SysRt += strcount;
  try  { File.Delete(syrtdtflpth); }   // than delete  installation date file
  catch  { }

  //  and recreate new file with fresh date
  StreamWriter  fsInstDtFile =
  new  StreamWriter(new  FileStream(syrtdtflpth,
  FileMode.Create,
  FileAccess.Write));
  fsInstDtFile.Write(Dtfor_SysRt);
  fsInstDtFile.Close();
  }
  }
  else
  {
  // If  file doesn't exist, set install counter to 1 at 9th letter position, 
  // and add to  file
  Dtfor_SysRt += "1";
  //  Now write to file
  StreamWriter  fsInstDtFile =
  new  StreamWriter(
  new FileStream
  (syrtdtflpth,
  FileMode.Create,
  FileAccess.Write));
  fsInstDtFile.Write(Dtfor_SysRt);
  fsInstDtFile.Close();
  }
  }

  private  string RetuInstalCounter(string syrtdtflpth)
  {
  StreamReader  fsInstDtFile =
  new  StreamReader(new  FileStream(syrtdtflpth,
  FileMode.Open,
  FileAccess.Read));
  string  instdtAndCounter = fsInstDtFile.ReadToEnd();
  fsInstDtFile.Close();

  // now  ripoff install counter
  string  inscount = instdtAndCounter.Substring(8, 1);
  return  inscount;
  }

  static void Main(string[]  args)
  {
  Program  p = new Program();
  p.md_instdt();
  p.ed_rgy();
  p.ed_sysrt();
  }
  }
  }

第二步

一个必须首先执行的特殊验证码应附加到我们应用程序的主可执行文件中。演示版安装后,每次应用程序运行时,此代码都会验证到期日期。

下面的源代码首先读取存储在 *SystemRoot* 文件夹中的文件信息,并完成以下步骤:

  • 验证系统日期并计算已过天数
  • 评估到期情况

源代码示例

  //  MainForm.cs
  //  This form shall be used in Main Project’s program.cs file
  using System;
  using  System.Collections.Generic;
  using  System.ComponentModel;
  using  System.Data;
  using  System.Drawing;
  using  System.Text;
  using  System.Windows.Forms;
  using System.IO;
  using  Microsoft.Win32;
  using  System.Globalization;

namespace Terminator
  {
  public partial class MainForm : Form
  {
  string  SysRtDtFilePath;

  public  MainForm()
  {
  InitializeComponent();
  SysRtDtFilePath = Environment.GetEnvironmentVariable("SystemRoot");
  }

  private  void MainForm_Load(object  sender, EventArgs e)
  {
  SysRtDtFilePath += "\\demdt.dtd";
  if  (File.Exists(SysRtDtFilePath))
  {
  try
  {
  StreamReader  fsInstDtFile =
  new StreamReader(new FileStream(SysRtDtFilePath,
  FileMode.Open,
  FileAccess.Read));
  string  instdt = fsInstDtFile.ReadToEnd();

  if  (String.IsNullOrEmpty(instdt) == false)
  doEvaluation(instdt);
  fsInstDtFile.Close();
  }
  catch
  {
  MessageBox.Show("File Read or system date format error", "Information",
  MessageBoxButtons.OK, MessageBoxIcon.Error);
  }
  }
  else
  {
  MessageBox.Show("Either evaluation period expired or file manually  corrupted.",
  "Information",  MessageBoxButtons.OK, MessageBoxIcon.Information);
  }
  }

  private  void doEvaluation(string  insdt)
  {
  string  rightdt = insdt.Trim();
  string  dy = rightdt.Substring(0, 2);
  string  mon = rightdt.Substring(2, 2);
  string  yr = rightdt.Substring(4, 4);

  // First  make installation date string:
  string  mdt = dy + "/" + mon + "/" + yr; //  +" " + "12:00:00";
  DateTime  curdt = DateTime.Today;

  IFormatProvider  culture = new CultureInfo("fr-FR", true);
  DateTime  Finstdt =
  DateTime.Parse(mdt,  culture, DateTimeStyles.NoCurrentDateDefault);

  if  (curdt < Finstdt)
  {
  label4.Text = "Invalid System date";
  MessageBox.Show("Invalid System date", "Information",
  MessageBoxButtons.OK,  MessageBoxIcon.Information);
  Application.Exit();
  }

  DateTime  maxdt = Finstdt.AddDays(2);

  TimeSpan  diffs = maxdt - curdt; // get days lapsed
  int  d = diffs.Days;

  if  (d < 0)
  {
  label4.Text = "nil";
  MessageBox.Show("Your evaluation period has been expired
  or not  Activated." + "\n" +
  "This  trial version is only for Demo purposes.
  To freely use Data Theft controller  (Demo) software" + "\n"  +
  "created  by ABC Technologies, 
  you need to purchase this Software from ABC Technologies.");
  Application.Exit();
  }
  else
  {
  label4.Text =  d.ToString().Trim() + " days left";
  btnStart.Visible = true;
  }
  }

  private  void btnStart_Click(object  sender, EventArgs e)
  {
  Form  fm = new Form1();  // First page of our application
  this.Hide();  // hide main form
  fm.ShowDialog(this);
  }

  private  void btnCancel_Click(object  sender, EventArgs e)
  {
  this.Close();
  }
  }
  }

现在将以下代码行添加到我们主应用程序的 *Program.cs* 文件中

namespace Terminator
  {
  static class Program
  {
  // my global  variables
  public static string  strPwdFilePath =
  Environment.GetEnvironmentVariable("SystemRoot");
  public static bool  isPwdEnabled = false;

  [STAThread]
  static void Main()
  {
  Application.EnableVisualStyles();
  Application.SetCompatibleTextRenderingDefault(false);
  Application.Run(new MainForm());
  }
  } 

摘要

再次重申,本文仅为初学者提供保护其应用程序的基本知识。在此级别的策略可以更加复杂和具有竞争力。

© . All rights reserved.